@cratis/pi 7.102.0 → 7.103.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 (140) hide show
  1. package/package/corpus/harnesses/copilot/instructions/profiles.instructions.md +10 -1
  2. package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +2 -0
  3. package/package/corpus/harnesses/copilot/instructions/secrets.instructions.md +4 -0
  4. package/package/corpus/hooks/README.md +11 -1
  5. package/package/corpus/hooks/scripts/cratis-check-pr.mjs +12 -1
  6. package/package/corpus/hooks/scripts/cratis-guard-secrets.sh +79 -23
  7. package/package/corpus/hooks/scripts/cratis-guard-writes.sh +145 -40
  8. package/package/corpus/rules/profiles.md +10 -1
  9. package/package/corpus/rules/pull-requests.md +2 -0
  10. package/package/corpus/rules/secrets.md +4 -0
  11. package/package/corpus/skills/analyzing-dotnet-performance/LICENSE +23 -0
  12. package/package/corpus/skills/analyzing-dotnet-performance/NOTICE +36 -0
  13. package/package/corpus/skills/analyzing-dotnet-performance/SKILL.md +214 -0
  14. package/package/corpus/skills/analyzing-dotnet-performance/references/async-patterns.md +122 -0
  15. package/package/corpus/skills/analyzing-dotnet-performance/references/collections-and-linq.md +220 -0
  16. package/package/corpus/skills/analyzing-dotnet-performance/references/critical-patterns.md +291 -0
  17. package/package/corpus/skills/analyzing-dotnet-performance/references/io-and-serialization.md +135 -0
  18. package/package/corpus/skills/analyzing-dotnet-performance/references/memory-and-strings.md +219 -0
  19. package/package/corpus/skills/analyzing-dotnet-performance/references/regex-patterns.md +95 -0
  20. package/package/corpus/skills/analyzing-dotnet-performance/references/structural-patterns.md +38 -0
  21. package/package/corpus/skills/binlog-generation/LICENSE +23 -0
  22. package/package/corpus/skills/binlog-generation/NOTICE +22 -0
  23. package/package/corpus/skills/binlog-generation/SKILL.md +129 -0
  24. package/package/corpus/skills/check-bin-obj-clash/LICENSE +23 -0
  25. package/package/corpus/skills/check-bin-obj-clash/NOTICE +27 -0
  26. package/package/corpus/skills/check-bin-obj-clash/SKILL.md +127 -0
  27. package/package/corpus/skills/check-bin-obj-clash/references/common-causes-and-fixes.md +206 -0
  28. package/package/corpus/skills/coverage-analysis/LICENSE +23 -0
  29. package/package/corpus/skills/coverage-analysis/NOTICE +32 -0
  30. package/package/corpus/skills/coverage-analysis/SKILL.md +198 -0
  31. package/package/corpus/skills/coverage-analysis/references/guidelines.md +68 -0
  32. package/package/corpus/skills/coverage-analysis/references/output-format.md +91 -0
  33. package/package/corpus/skills/coverage-analysis/references/report-generation.md +58 -0
  34. package/package/corpus/skills/coverage-analysis/references/setup-discovery.md +307 -0
  35. package/package/corpus/skills/coverage-analysis/scripts/Compute-CrapScores.ps1 +80 -0
  36. package/package/corpus/skills/coverage-analysis/scripts/CoverageData.ps1 +272 -0
  37. package/package/corpus/skills/coverage-analysis/scripts/Extract-MethodCoverage.ps1 +65 -0
  38. package/package/corpus/skills/csharp-refactoring/LICENSE +23 -0
  39. package/package/corpus/skills/csharp-refactoring/NOTICE +22 -0
  40. package/package/corpus/skills/csharp-refactoring/SKILL.md +175 -0
  41. package/package/corpus/skills/csharp-refactoring/references/operation-catalog.md +37 -0
  42. package/package/corpus/skills/directory-build-organization/LICENSE +23 -0
  43. package/package/corpus/skills/directory-build-organization/NOTICE +21 -0
  44. package/package/corpus/skills/directory-build-organization/SKILL.md +205 -0
  45. package/package/corpus/skills/directory-build-organization/references/common-patterns.md +56 -0
  46. package/package/corpus/skills/directory-build-organization/references/multi-level-examples.md +167 -0
  47. package/package/corpus/skills/directory-build-organization/references/targetframework-props-pitfall.md +54 -0
  48. package/package/corpus/skills/dotnet-aot-compat/LICENSE +23 -0
  49. package/package/corpus/skills/dotnet-aot-compat/NOTICE +18 -0
  50. package/package/corpus/skills/dotnet-aot-compat/SKILL.md +265 -0
  51. package/package/corpus/skills/dotnet-aot-compat/references/polyfills.md +43 -0
  52. package/package/corpus/skills/dotnet-trace-collect/LICENSE +23 -0
  53. package/package/corpus/skills/dotnet-trace-collect/NOTICE +65 -0
  54. package/package/corpus/skills/dotnet-trace-collect/SKILL.md +116 -0
  55. package/package/corpus/skills/dotnet-trace-collect/references/dotnet-monitor.md +97 -0
  56. package/package/corpus/skills/dotnet-trace-collect/references/dotnet-trace-collect-linux.md +84 -0
  57. package/package/corpus/skills/dotnet-trace-collect/references/dotnet-trace-collect.md +91 -0
  58. package/package/corpus/skills/dotnet-trace-collect/references/perfcollect.md +200 -0
  59. package/package/corpus/skills/dotnet-trace-collect/references/perfview.md +141 -0
  60. package/package/corpus/skills/dotnet-trace-collect/references/tool-selection.md +160 -0
  61. package/package/corpus/skills/dump-collect/LICENSE +23 -0
  62. package/package/corpus/skills/dump-collect/NOTICE +40 -0
  63. package/package/corpus/skills/dump-collect/SKILL.md +97 -0
  64. package/package/corpus/skills/dump-collect/references/container-dumps.md +412 -0
  65. package/package/corpus/skills/dump-collect/references/coreclr-dumps.md +108 -0
  66. package/package/corpus/skills/dump-collect/references/nativeaot-dumps.md +280 -0
  67. package/package/corpus/skills/eliminate-redundant-restores/LICENSE +23 -0
  68. package/package/corpus/skills/eliminate-redundant-restores/NOTICE +19 -0
  69. package/package/corpus/skills/eliminate-redundant-restores/SKILL.md +112 -0
  70. package/package/corpus/skills/extension-points/LICENSE +23 -0
  71. package/package/corpus/skills/extension-points/NOTICE +18 -0
  72. package/package/corpus/skills/extension-points/SKILL.md +248 -0
  73. package/package/corpus/skills/filter-syntax/LICENSE +23 -0
  74. package/package/corpus/skills/filter-syntax/NOTICE +17 -0
  75. package/package/corpus/skills/filter-syntax/SKILL.md +179 -0
  76. package/package/corpus/skills/including-generated-files/LICENSE +23 -0
  77. package/package/corpus/skills/including-generated-files/NOTICE +17 -0
  78. package/package/corpus/skills/including-generated-files/SKILL.md +139 -0
  79. package/package/corpus/skills/microbenchmarking/LICENSE +23 -0
  80. package/package/corpus/skills/microbenchmarking/NOTICE +36 -0
  81. package/package/corpus/skills/microbenchmarking/SKILL.md +131 -0
  82. package/package/corpus/skills/microbenchmarking/references/bdn-internals-and-tuning.md +143 -0
  83. package/package/corpus/skills/microbenchmarking/references/comparison-strategies.md +200 -0
  84. package/package/corpus/skills/microbenchmarking/references/diagnosers-and-exporters.md +150 -0
  85. package/package/corpus/skills/microbenchmarking/references/project-setup-and-running.md +189 -0
  86. package/package/corpus/skills/microbenchmarking/references/writing-benchmarks.md +310 -0
  87. package/package/corpus/skills/msbuild/LICENSE +23 -0
  88. package/package/corpus/skills/msbuild/NOTICE +55 -0
  89. package/package/corpus/skills/msbuild/SKILL.md +117 -0
  90. package/package/corpus/skills/msbuild/references/antipatterns/additional-antipatterns.md +291 -0
  91. package/package/corpus/skills/msbuild/references/antipatterns/incremental-build-inputs-outputs.md +57 -0
  92. package/package/corpus/skills/msbuild/references/antipatterns/private-assets.md +29 -0
  93. package/package/corpus/skills/msbuild/references/binlog-failure-analysis.md +85 -0
  94. package/package/corpus/skills/msbuild/references/binlog-generation.md +69 -0
  95. package/package/corpus/skills/msbuild/references/build-perf-baseline.md +493 -0
  96. package/package/corpus/skills/msbuild/references/build-perf-diagnostics.md +268 -0
  97. package/package/corpus/skills/msbuild/references/copy-to-output-directory.md +183 -0
  98. package/package/corpus/skills/msbuild/references/eval-performance.md +190 -0
  99. package/package/corpus/skills/msbuild/references/extension-points.md +281 -0
  100. package/package/corpus/skills/msbuild/references/incremental-build.md +365 -0
  101. package/package/corpus/skills/msbuild/references/msbuild-antipatterns.md +401 -0
  102. package/package/corpus/skills/orleans/LICENSE +21 -0
  103. package/package/corpus/skills/orleans/NOTICE +64 -0
  104. package/package/corpus/skills/orleans/SKILL.md +140 -0
  105. package/package/corpus/skills/orleans/references/anti-patterns.md +660 -0
  106. package/package/corpus/skills/orleans/references/configuration-api.md +933 -0
  107. package/package/corpus/skills/orleans/references/examples.md +66 -0
  108. package/package/corpus/skills/orleans/references/grain-api.md +784 -0
  109. package/package/corpus/skills/orleans/references/grains.md +75 -0
  110. package/package/corpus/skills/orleans/references/hosting.md +71 -0
  111. package/package/corpus/skills/orleans/references/implementation.md +591 -0
  112. package/package/corpus/skills/orleans/references/official-docs-index.md +250 -0
  113. package/package/corpus/skills/orleans/references/patterns.md +811 -0
  114. package/package/corpus/skills/orleans/references/persistence-api.md +495 -0
  115. package/package/corpus/skills/orleans/references/primitive-selection.md +35 -0
  116. package/package/corpus/skills/orleans/references/scheduling-and-services.md +295 -0
  117. package/package/corpus/skills/orleans/references/serialization-api.md +299 -0
  118. package/package/corpus/skills/orleans/references/streaming-api.md +396 -0
  119. package/package/corpus/skills/orleans/references/testing-patterns.md +210 -0
  120. package/package/corpus/skills/platform-detection/LICENSE +23 -0
  121. package/package/corpus/skills/platform-detection/NOTICE +17 -0
  122. package/package/corpus/skills/platform-detection/SKILL.md +230 -0
  123. package/package/corpus/skills/platform-detection/references/command-mode.md +27 -0
  124. package/package/corpus/skills/profiling/LICENSE +21 -0
  125. package/package/corpus/skills/profiling/NOTICE +50 -0
  126. package/package/corpus/skills/profiling/SKILL.md +144 -0
  127. package/package/corpus/skills/profiling/references/commands.md +439 -0
  128. package/package/corpus/skills/profiling/references/patterns.md +586 -0
  129. package/package/corpus/skills/profiling/references/profiling.md +190 -0
  130. package/package/corpus/skills/run-tests/LICENSE +23 -0
  131. package/package/corpus/skills/run-tests/NOTICE +19 -0
  132. package/package/corpus/skills/run-tests/SKILL.md +305 -0
  133. package/package/corpus/skills/target-authoring/LICENSE +23 -0
  134. package/package/corpus/skills/target-authoring/NOTICE +17 -0
  135. package/package/corpus/skills/target-authoring/SKILL.md +165 -0
  136. package/package/corpus/skills/vectorization/LICENSE +23 -0
  137. package/package/corpus/skills/vectorization/NOTICE +17 -0
  138. package/package/corpus/skills/vectorization/SKILL.md +189 -0
  139. package/package/profile-catalog.json +85 -1
  140. package/package.json +1 -1
@@ -0,0 +1,205 @@
1
+ ---
2
+ name: directory-build-organization
3
+ description: 'Organizes shared MSBuild policy across Directory.Build.props, Directory.Build.targets, Directory.Build.rsp, and Directory.Packages.props: centralizing repeated properties, targets, and package versions, hierarchy and import structure, props-versus-targets placement, and folder or project exceptions. Use when two or more projects repeat MSBuild policy, or an existing Directory.Build hierarchy has an import, placement, or layering defect, even if only one project is affected. Not for a one-project repo without a Directory.Build file, property value or condition semantics, legacy-to-SDK migration, or non-MSBuild systems.'
4
+ license: MIT
5
+ ---
6
+
7
+ <!-- Modified by Cratis from dotnet's original (MIT): frontmatter, applicability, navigation and the changes listed in NOTICE. Upstream: https://github.com/dotnet/skills (plugins/dotnet-msbuild/skills/directory-build-organization/SKILL.md; see NOTICE) -->
8
+
9
+ # Organizing Build Infrastructure with Directory.Build Files
10
+
11
+ Cratis rules in `.cratis/ai/rules/` (including `csharp.md`, `specs.csharp.md`, and `orleans.md`) and the `cratis-*` skills win where they differ.
12
+
13
+ ## Intent control
14
+
15
+ - For "should we", "how should we organize", "recommend", "advise", or review
16
+ requests, inspect the actual project files and return a proposed layout only.
17
+ Do not create or edit files unless the user explicitly asks to apply, move,
18
+ centralize, or clean up the configuration.
19
+ - Before summarizing, verify which project retains each project-specific
20
+ property, item, or target. Name the actual file; do not infer it from sibling
21
+ names.
22
+ - Recommend a verification command only after discovering a real `.sln`,
23
+ `.slnx`, `.proj`, or project file at that path. If no repo-root entry point
24
+ exists, give commands for the discovered projects or state that the entry
25
+ point was not found.
26
+ - Every advice response must explain that `Microsoft.Common.props` searches
27
+ upward from each project and automatically imports the nearest
28
+ `Directory.Build.props` early; project values can then override shared
29
+ defaults. Explain the equivalent late `Microsoft.Common.targets` import when
30
+ recommending `Directory.Build.targets`.
31
+
32
+ ## Directory.Build.props vs Directory.Build.targets
33
+
34
+ Understanding which file to use is critical. They differ in **when** they are imported during evaluation:
35
+
36
+ **Evaluation order:**
37
+
38
+ ```
39
+ Microsoft.Common.props imports Directory.Build.props early
40
+ → project body and package/project imports evaluate
41
+ → Microsoft.Common.targets imports Directory.Build.targets late
42
+ ```
43
+
44
+ | Use `.props` for | Use `.targets` for |
45
+ |---|---|
46
+ | Setting property defaults | Custom build targets |
47
+ | Common item definitions | Late-bound property overrides |
48
+ | Properties projects can override | Post-build steps |
49
+ | Assembly/package metadata | Conditional logic on final values |
50
+ | Analyzer PackageReferences | Targets that depend on SDK-defined properties |
51
+
52
+ **Rule of thumb:** Properties and items go in `.props`. Custom targets and late-bound logic go in `.targets`.
53
+
54
+ Because `.props` is imported before the project file, the project can override any value set there. Because `.targets` is imported after everything, it gets the final say—but projects cannot override `.targets` values.
55
+
56
+ ### ⚠️ Critical: TargetFramework Availability in .props vs .targets
57
+
58
+ **Property conditions on `$(TargetFramework)` in `.props` files silently fail for single-targeting projects** — the property is empty during `.props` evaluation. Move TFM-conditional properties to `.targets` instead. ItemGroup and Target conditions are not affected.
59
+
60
+ See [targetframework-props-pitfall.md](references/targetframework-props-pitfall.md) for the full explanation.
61
+
62
+ ## Directory.Build.props
63
+
64
+ Good candidates: language settings, assembly/package metadata, build warnings, code analysis, common analyzers.
65
+
66
+ ```xml
67
+ <Project>
68
+ <PropertyGroup>
69
+ <Nullable>enable</Nullable>
70
+ <ImplicitUsings>enable</ImplicitUsings>
71
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
72
+ <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
73
+ <Company>Contoso</Company>
74
+ <Authors>Contoso Engineering</Authors>
75
+ </PropertyGroup>
76
+ </Project>
77
+ ```
78
+
79
+ **Do NOT put here:** project-specific TFMs, project-specific PackageReferences, targets/build logic, or properties depending on SDK-defined values (not available during `.props` evaluation).
80
+
81
+ ## Directory.Build.targets
82
+
83
+ Good candidates: custom build targets, late-bound property overrides (values depending on SDK properties), post-build validation.
84
+
85
+ ```xml
86
+ <Project>
87
+ <Target Name="ValidateProjectSettings" BeforeTargets="Build">
88
+ <Error Text="All libraries must target netstandard2.0 or higher"
89
+ Condition="'$(OutputType)' == 'Library' AND '$(TargetFramework)' == 'net472'" />
90
+ </Target>
91
+
92
+ <PropertyGroup>
93
+ <!-- DocumentationFile depends on OutputPath, which is set by the SDK -->
94
+ <DocumentationFile Condition="'$(IsPackable)' == 'true'">$(OutputPath)$(AssemblyName).xml</DocumentationFile>
95
+ </PropertyGroup>
96
+ </Project>
97
+ ```
98
+
99
+ ## Directory.Packages.props (Central Package Management)
100
+
101
+ Central Package Management (CPM) provides a single source of truth for all NuGet package versions. See [https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management](https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management) for details.
102
+
103
+ **Enable CPM in `Directory.Packages.props` at the repo root:**
104
+
105
+ ```xml
106
+ <Project>
107
+ <PropertyGroup>
108
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
109
+ </PropertyGroup>
110
+
111
+ <ItemGroup>
112
+ <PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
113
+ <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
114
+ <PackageVersion Include="xunit" Version="2.9.0" />
115
+ <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
116
+ </ItemGroup>
117
+
118
+ <ItemGroup>
119
+ <!-- GlobalPackageReference applies to ALL projects — great for analyzers -->
120
+ <GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
121
+ <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" />
122
+ </ItemGroup>
123
+ </Project>
124
+ ```
125
+
126
+ ## Directory.Build.rsp
127
+
128
+ Contains default MSBuild CLI arguments applied to all builds under the directory tree.
129
+
130
+ **Example `Directory.Build.rsp`:**
131
+
132
+ ```
133
+ /maxcpucount
134
+ /nodeReuse:false
135
+ /consoleLoggerParameters:Summary;ForceNoAlign
136
+ /warnAsMessage:MSB3277
137
+ ```
138
+
139
+ - Works with both `msbuild` and `dotnet` CLI in modern .NET versions
140
+ - Great for enforcing consistent CI and local build flags
141
+ - Each argument goes on its own line
142
+
143
+ ## Multi-level Directory.Build Files
144
+
145
+ MSBuild only auto-imports the **first** `Directory.Build.props` (or `.targets`) it finds walking up from the project directory. To chain multiple levels, explicitly import the parent at the **top** of the inner file. See [multi-level-examples](references/multi-level-examples.md) for full file examples.
146
+
147
+ ```xml
148
+ <Project>
149
+ <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"
150
+ Condition="Exists('$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))')" />
151
+
152
+ <!-- Inner-level overrides go here -->
153
+ </Project>
154
+ ```
155
+
156
+ **Example layout:**
157
+
158
+ ```
159
+ repo/
160
+ Directory.Build.props ← repo-wide (lang version, company info, analyzers)
161
+ Directory.Build.targets ← repo-wide targets
162
+ Directory.Packages.props ← central package versions
163
+ src/
164
+ Directory.Build.props ← src-specific (imports repo-level, sets IsPackable=true)
165
+ test/
166
+ Directory.Build.props ← test-specific (imports repo-level, sets IsPackable=false, adds test packages)
167
+ ```
168
+
169
+ ## Artifact Output Layout (.NET 8+)
170
+
171
+ Set `<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>` in `Directory.Build.props` to automatically produce project-name-separated `bin/`, `obj/`, and `publish/` directories under a single `artifacts/` folder, avoiding bin/obj clashes by default. See [common-patterns](references/common-patterns.md) for the directory layout and additional patterns (conditional settings by project type, post-pack validation).
172
+
173
+ ## Workflow: Organizing Build Infrastructure
174
+
175
+ 1. **Audit all `.csproj` files** — Catalog every `<PropertyGroup>`, `<ItemGroup>`, and custom `<Target>` across the solution. Note which settings repeat and which are project-specific.
176
+ 2. **Create root `Directory.Build.props`** — Move shared property defaults (LangVersion, Nullable, TreatWarningsAsErrors, metadata) here. These are imported before the project file so projects can override them.
177
+ 3. **Create root `Directory.Build.targets`** — Move custom build targets, post-build validation, and any properties that depend on SDK-defined values (e.g., `OutputPath`, `TargetFramework` for single-targeting projects) here. These are imported after the SDK so all properties are available.
178
+ 4. **Create `Directory.Packages.props`** — Enable Central Package Management (`ManagePackageVersionsCentrally`), list all `PackageVersion` entries, and remove `Version=` from `PackageReference` items in `.csproj` files.
179
+ 5. **Set up multi-level hierarchy** — Create inner `Directory.Build.props` files for `src/` and `test/` folders with distinct settings. Use `GetPathOfFileAbove` to chain to the parent.
180
+ 6. **Simplify `.csproj` files** — Remove all centralized properties, version attributes, and duplicated targets. Each project should only contain what is unique to it.
181
+ 7. **Validate** — Run restore/build against the discovered `.sln`, `.slnx`,
182
+ `.proj`, or project path, for example
183
+ `dotnet restore <entrypoint> && dotnet build <entrypoint>`. If no root
184
+ entrypoint exists, validate each discovered project explicitly instead of
185
+ claiming a repo-root build. Use
186
+ `dotnet msbuild <project> -pp:output.xml` to inspect the final merged view.
187
+
188
+ ## Troubleshooting
189
+
190
+ | Problem | Cause | Fix |
191
+ |---|---|---|
192
+ | `Directory.Build.props` isn't picked up | File name casing wrong (exact match required on Linux/macOS) | Verify exact casing: `Directory.Build.props` (capital D, B) |
193
+ | Properties from `.props` are ignored by projects | Project sets the same property after the import | Move the property to `Directory.Build.targets` to set it after the project |
194
+ | Multi-level import doesn't work | Missing `GetPathOfFileAbove` import in inner file | Add the `<Import>` element at the top of the inner file (see Multi-level section) |
195
+ | Properties using SDK values are empty in `.props` | SDK properties aren't defined yet during `.props` evaluation | Move to `.targets` which is imported after the SDK |
196
+ | `Directory.Packages.props` not found | File not at repo root or not named exactly | Must be named `Directory.Packages.props` and at or above the project directory |
197
+ | Property condition on `$(TargetFramework)` doesn't match in `.props` | `TargetFramework` isn't set yet for single-targeting projects during `.props` evaluation | Move property to `.targets`, or use ItemGroup/Target conditions instead (which evaluate late) |
198
+
199
+ **Diagnosis:** Use the preprocessed project output to see all imports and final property values:
200
+
201
+ ```bash
202
+ dotnet msbuild -pp:output.xml MyProject.csproj
203
+ ```
204
+
205
+ This expands all imports inline so you can see exactly where each property is set and what the final evaluated value is.
@@ -0,0 +1,56 @@
1
+ # Common Directory.Build Patterns
2
+
3
+ ## Conditional Settings by Project Type
4
+
5
+ Detect test projects by naming convention in `Directory.Build.props`:
6
+
7
+ ```xml
8
+ <PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests')) OR $(MSBuildProjectName.EndsWith('.UnitTests'))">
9
+ <IsPackable>false</IsPackable>
10
+ <IsTestProject>true</IsTestProject>
11
+ </PropertyGroup>
12
+ ```
13
+
14
+ Use `Directory.Build.targets` for conditions on SDK-defined properties like `OutputType`:
15
+
16
+ ```xml
17
+ <PropertyGroup Condition="'$(OutputType)' == 'Exe'">
18
+ <SelfContained>false</SelfContained>
19
+ </PropertyGroup>
20
+
21
+ <PropertyGroup Condition="'$(OutputType)' == 'Library' AND '$(IsTestProject)' != 'true'">
22
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
23
+ </PropertyGroup>
24
+ ```
25
+
26
+ ## Post-Build Validation
27
+
28
+ Validate that `Pack` produced the expected output:
29
+
30
+ ```xml
31
+ <Target Name="ValidatePackageOutput" AfterTargets="Pack"
32
+ Condition="'$(IsPackable)' == 'true'">
33
+ <Error Text="Package was not created at $(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg"
34
+ Condition="!Exists('$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg')" />
35
+ </Target>
36
+ ```
37
+
38
+ ## Artifact Output Layout (.NET 8+)
39
+
40
+ Setting `ArtifactsPath` in `Directory.Build.props` produces this structure:
41
+
42
+ ```
43
+ artifacts/
44
+ bin/
45
+ MyLib/
46
+ debug/
47
+ release/
48
+ MyApp/
49
+ debug/
50
+ release/
51
+ obj/
52
+ MyLib/
53
+ MyApp/
54
+ publish/
55
+ MyApp/
56
+ ```
@@ -0,0 +1,167 @@
1
+ # Multi-level Directory.Build Examples
2
+
3
+ ## Contents
4
+
5
+ - Repo-level `Directory.Build.props`
6
+ - `src/Directory.Build.props`
7
+ - `test/Directory.Build.props`
8
+ - Before/After: Centralizing Duplicated Settings
9
+
10
+ Full file examples for a typical multi-level repo layout.
11
+
12
+ ## Repo-level `Directory.Build.props`
13
+
14
+ ```xml
15
+ <Project>
16
+
17
+ <PropertyGroup>
18
+ <Nullable>enable</Nullable>
19
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
20
+ </PropertyGroup>
21
+
22
+ </Project>
23
+ ```
24
+
25
+ ## `src/Directory.Build.props`
26
+
27
+ ```xml
28
+ <Project>
29
+
30
+ <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"
31
+ Condition="Exists('$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))')" />
32
+
33
+ <PropertyGroup>
34
+ <IsPackable>true</IsPackable>
35
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
36
+ </PropertyGroup>
37
+
38
+ </Project>
39
+ ```
40
+
41
+ ## `test/Directory.Build.props`
42
+
43
+ ```xml
44
+ <Project>
45
+
46
+ <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"
47
+ Condition="Exists('$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))')" />
48
+
49
+ <PropertyGroup>
50
+ <IsPackable>false</IsPackable>
51
+ <NoWarn>$(NoWarn);CS1591</NoWarn>
52
+ </PropertyGroup>
53
+
54
+ <ItemGroup>
55
+ <PackageReference Include="xunit" />
56
+ <PackageReference Include="xunit.runner.visualstudio" />
57
+ <PackageReference Include="Microsoft.NET.Test.Sdk" />
58
+ <PackageReference Include="NSubstitute" />
59
+ </ItemGroup>
60
+
61
+ </Project>
62
+ ```
63
+
64
+ ## Before/After: Centralizing Duplicated Settings
65
+
66
+ **Before — duplicated settings in every .csproj:**
67
+
68
+ ```xml
69
+ <!-- src/LibA/LibA.csproj -->
70
+ <Project Sdk="Microsoft.NET.Sdk">
71
+
72
+ <PropertyGroup>
73
+ <TargetFramework>net8.0</TargetFramework>
74
+ <Nullable>enable</Nullable>
75
+ <ImplicitUsings>enable</ImplicitUsings>
76
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
77
+ <Company>Contoso</Company>
78
+ <Authors>Contoso Engineering</Authors>
79
+ </PropertyGroup>
80
+
81
+ <ItemGroup>
82
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
83
+ <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
84
+ </ItemGroup>
85
+
86
+ </Project>
87
+
88
+ <!-- src/LibB/LibB.csproj — same boilerplate repeated -->
89
+ <Project Sdk="Microsoft.NET.Sdk">
90
+
91
+ <PropertyGroup>
92
+ <TargetFramework>net8.0</TargetFramework>
93
+ <Nullable>enable</Nullable>
94
+ <ImplicitUsings>enable</ImplicitUsings>
95
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
96
+ <Company>Contoso</Company>
97
+ <Authors>Contoso Engineering</Authors>
98
+ </PropertyGroup>
99
+
100
+ <ItemGroup>
101
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
102
+ <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
103
+ </ItemGroup>
104
+
105
+ </Project>
106
+ ```
107
+
108
+ **After — centralized with Directory.Build files:**
109
+
110
+ ```xml
111
+ <!-- Directory.Build.props -->
112
+ <Project>
113
+
114
+ <PropertyGroup>
115
+ <Nullable>enable</Nullable>
116
+ <ImplicitUsings>enable</ImplicitUsings>
117
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
118
+ <Company>Contoso</Company>
119
+ <Authors>Contoso Engineering</Authors>
120
+ </PropertyGroup>
121
+
122
+ </Project>
123
+
124
+ <!-- Directory.Packages.props -->
125
+ <Project>
126
+
127
+ <PropertyGroup>
128
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
129
+ </PropertyGroup>
130
+
131
+ <ItemGroup>
132
+ <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
133
+ <PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
134
+ </ItemGroup>
135
+
136
+ <ItemGroup>
137
+ <GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
138
+ </ItemGroup>
139
+
140
+ </Project>
141
+
142
+ <!-- src/LibA/LibA.csproj — clean and minimal -->
143
+ <Project Sdk="Microsoft.NET.Sdk">
144
+
145
+ <PropertyGroup>
146
+ <TargetFramework>net8.0</TargetFramework>
147
+ </PropertyGroup>
148
+
149
+ <ItemGroup>
150
+ <PackageReference Include="Newtonsoft.Json" />
151
+ </ItemGroup>
152
+
153
+ </Project>
154
+
155
+ <!-- src/LibB/LibB.csproj — clean and minimal -->
156
+ <Project Sdk="Microsoft.NET.Sdk">
157
+
158
+ <PropertyGroup>
159
+ <TargetFramework>net8.0</TargetFramework>
160
+ </PropertyGroup>
161
+
162
+ <ItemGroup>
163
+ <PackageReference Include="Microsoft.Extensions.Logging" />
164
+ </ItemGroup>
165
+
166
+ </Project>
167
+ ```
@@ -0,0 +1,54 @@
1
+ # AP-21: Property Conditioned on TargetFramework in .props Files
2
+
3
+ **Smell**: `<PropertyGroup Condition="'$(TargetFramework)' == '...'">` or `<Property Condition="'$(TargetFramework)' == '...'">` in `Directory.Build.props` or any `.props` file imported before the project body.
4
+
5
+ **Why it's bad**: `$(TargetFramework)` is NOT reliably available in `Directory.Build.props` or any `.props` file imported before the project body. It is only set that early for multi-targeting projects, which receive `TargetFramework` as a global property from the outer build. Single-targeting projects (using singular `<TargetFramework>`) set it in the project body, which is evaluated *after* `.props`. This means property conditions on `$(TargetFramework)` in `.props` files silently fail for single-targeting projects — the condition never matches because the property is empty. This applies to both `<PropertyGroup Condition="...">` and individual `<Property Condition="...">` elements.
6
+
7
+ For a detailed explanation of MSBuild's evaluation and execution phases, see [Build process overview](https://learn.microsoft.com/en-us/visualstudio/msbuild/build-process-overview).
8
+
9
+ ```xml
10
+ <!-- BAD: In Directory.Build.props — TargetFramework may be empty here -->
11
+ <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
12
+ <DefineConstants>$(DefineConstants);MY_FEATURE</DefineConstants>
13
+ </PropertyGroup>
14
+
15
+ <!-- ALSO BAD: Condition on the property itself has the same problem -->
16
+ <PropertyGroup>
17
+ <DefineConstants Condition="'$(TargetFramework)' == 'net8.0'">$(DefineConstants);MY_FEATURE</DefineConstants>
18
+ </PropertyGroup>
19
+
20
+ <!-- GOOD: In Directory.Build.targets — TargetFramework is always available -->
21
+ <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
22
+ <DefineConstants>$(DefineConstants);MY_FEATURE</DefineConstants>
23
+ </PropertyGroup>
24
+
25
+ <!-- ALSO GOOD: In the project file itself -->
26
+ <!-- MyProject.csproj -->
27
+ <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
28
+ <DefineConstants>$(DefineConstants);MY_FEATURE</DefineConstants>
29
+ </PropertyGroup>
30
+ ```
31
+
32
+ **⚠️ Item and Target conditions are NOT affected.** This restriction applies ONLY to property conditions (`<PropertyGroup Condition="...">` and `<Property Condition="...">`). Item conditions (`<ItemGroup Condition="...">`) and Target conditions in `.props` files are SAFE because items and targets evaluate after all properties (including those set in the project body) have been evaluated. This includes `PackageVersion` items in `Directory.Packages.props`, `PackageReference` items in `Directory.Build.props`, and any other item types.
33
+
34
+ **Do NOT flag the following patterns — they are correct:**
35
+
36
+ ```xml
37
+ <!-- OK in Directory.Build.props — ItemGroup conditions evaluate late -->
38
+ <ItemGroup Condition="'$(TargetFramework)' == 'net472'">
39
+ <PackageReference Include="System.Memory" />
40
+ </ItemGroup>
41
+
42
+ <!-- OK in Directory.Packages.props — PackageVersion items evaluate late -->
43
+ <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
44
+ <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
45
+ </ItemGroup>
46
+ <ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
47
+ <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
48
+ </ItemGroup>
49
+
50
+ <!-- OK — Individual item conditions also evaluate late -->
51
+ <ItemGroup>
52
+ <PackageReference Include="System.Memory" Condition="'$(TargetFramework)' == 'net472'" />
53
+ </ItemGroup>
54
+ ```
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) .NET Foundation and Contributors
4
+
5
+ All rights reserved.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ dotnet-aot-compat
2
+ Copyright (c) .NET Foundation and Contributors
3
+ Licensed under the MIT License. See LICENSE.
4
+
5
+ Upstream source: https://github.com/dotnet/skills/blob/a6bf43ab61967c30919334986515163ab24d7635/plugins/dotnet-upgrade/skills/dotnet-aot-compat/SKILL.md
6
+
7
+ Changes made by Cratis:
8
+
9
+ LICENSE:
10
+ - Copy upstream MIT license and copyright verbatim.
11
+
12
+ SKILL.md:
13
+ - Normalize frontmatter serialization, add MIT license where absent; preserve name and description.
14
+ - Add marked modification/source comment and applicability/Cratis precedence line with the skill-specific safety, ownership or compatibility caveat.
15
+ - Rewrite the description to the Cratis shape (what it does, Use when, Not for) and drop references to skills that are not part of this corpus.
16
+ - Remove the invalid [JsonSerializerContext] attribute from the source-generated JSON example; the context is a partial class deriving from JsonSerializerContext.
17
+
18
+ NOTICE: Add this attribution, change list, and any download/execution disclosure.