@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.
- package/package/corpus/harnesses/copilot/instructions/profiles.instructions.md +10 -1
- package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +2 -0
- package/package/corpus/harnesses/copilot/instructions/secrets.instructions.md +4 -0
- package/package/corpus/hooks/README.md +11 -1
- package/package/corpus/hooks/scripts/cratis-check-pr.mjs +12 -1
- package/package/corpus/hooks/scripts/cratis-guard-secrets.sh +79 -23
- package/package/corpus/hooks/scripts/cratis-guard-writes.sh +145 -40
- package/package/corpus/rules/profiles.md +10 -1
- package/package/corpus/rules/pull-requests.md +2 -0
- package/package/corpus/rules/secrets.md +4 -0
- package/package/corpus/skills/analyzing-dotnet-performance/LICENSE +23 -0
- package/package/corpus/skills/analyzing-dotnet-performance/NOTICE +36 -0
- package/package/corpus/skills/analyzing-dotnet-performance/SKILL.md +214 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/async-patterns.md +122 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/collections-and-linq.md +220 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/critical-patterns.md +291 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/io-and-serialization.md +135 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/memory-and-strings.md +219 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/regex-patterns.md +95 -0
- package/package/corpus/skills/analyzing-dotnet-performance/references/structural-patterns.md +38 -0
- package/package/corpus/skills/binlog-generation/LICENSE +23 -0
- package/package/corpus/skills/binlog-generation/NOTICE +22 -0
- package/package/corpus/skills/binlog-generation/SKILL.md +129 -0
- package/package/corpus/skills/check-bin-obj-clash/LICENSE +23 -0
- package/package/corpus/skills/check-bin-obj-clash/NOTICE +27 -0
- package/package/corpus/skills/check-bin-obj-clash/SKILL.md +127 -0
- package/package/corpus/skills/check-bin-obj-clash/references/common-causes-and-fixes.md +206 -0
- package/package/corpus/skills/coverage-analysis/LICENSE +23 -0
- package/package/corpus/skills/coverage-analysis/NOTICE +32 -0
- package/package/corpus/skills/coverage-analysis/SKILL.md +198 -0
- package/package/corpus/skills/coverage-analysis/references/guidelines.md +68 -0
- package/package/corpus/skills/coverage-analysis/references/output-format.md +91 -0
- package/package/corpus/skills/coverage-analysis/references/report-generation.md +58 -0
- package/package/corpus/skills/coverage-analysis/references/setup-discovery.md +307 -0
- package/package/corpus/skills/coverage-analysis/scripts/Compute-CrapScores.ps1 +80 -0
- package/package/corpus/skills/coverage-analysis/scripts/CoverageData.ps1 +272 -0
- package/package/corpus/skills/coverage-analysis/scripts/Extract-MethodCoverage.ps1 +65 -0
- package/package/corpus/skills/csharp-refactoring/LICENSE +23 -0
- package/package/corpus/skills/csharp-refactoring/NOTICE +22 -0
- package/package/corpus/skills/csharp-refactoring/SKILL.md +175 -0
- package/package/corpus/skills/csharp-refactoring/references/operation-catalog.md +37 -0
- package/package/corpus/skills/directory-build-organization/LICENSE +23 -0
- package/package/corpus/skills/directory-build-organization/NOTICE +21 -0
- package/package/corpus/skills/directory-build-organization/SKILL.md +205 -0
- package/package/corpus/skills/directory-build-organization/references/common-patterns.md +56 -0
- package/package/corpus/skills/directory-build-organization/references/multi-level-examples.md +167 -0
- package/package/corpus/skills/directory-build-organization/references/targetframework-props-pitfall.md +54 -0
- package/package/corpus/skills/dotnet-aot-compat/LICENSE +23 -0
- package/package/corpus/skills/dotnet-aot-compat/NOTICE +18 -0
- package/package/corpus/skills/dotnet-aot-compat/SKILL.md +265 -0
- package/package/corpus/skills/dotnet-aot-compat/references/polyfills.md +43 -0
- package/package/corpus/skills/dotnet-trace-collect/LICENSE +23 -0
- package/package/corpus/skills/dotnet-trace-collect/NOTICE +65 -0
- package/package/corpus/skills/dotnet-trace-collect/SKILL.md +116 -0
- package/package/corpus/skills/dotnet-trace-collect/references/dotnet-monitor.md +97 -0
- package/package/corpus/skills/dotnet-trace-collect/references/dotnet-trace-collect-linux.md +84 -0
- package/package/corpus/skills/dotnet-trace-collect/references/dotnet-trace-collect.md +91 -0
- package/package/corpus/skills/dotnet-trace-collect/references/perfcollect.md +200 -0
- package/package/corpus/skills/dotnet-trace-collect/references/perfview.md +141 -0
- package/package/corpus/skills/dotnet-trace-collect/references/tool-selection.md +160 -0
- package/package/corpus/skills/dump-collect/LICENSE +23 -0
- package/package/corpus/skills/dump-collect/NOTICE +40 -0
- package/package/corpus/skills/dump-collect/SKILL.md +97 -0
- package/package/corpus/skills/dump-collect/references/container-dumps.md +412 -0
- package/package/corpus/skills/dump-collect/references/coreclr-dumps.md +108 -0
- package/package/corpus/skills/dump-collect/references/nativeaot-dumps.md +280 -0
- package/package/corpus/skills/eliminate-redundant-restores/LICENSE +23 -0
- package/package/corpus/skills/eliminate-redundant-restores/NOTICE +19 -0
- package/package/corpus/skills/eliminate-redundant-restores/SKILL.md +112 -0
- package/package/corpus/skills/extension-points/LICENSE +23 -0
- package/package/corpus/skills/extension-points/NOTICE +18 -0
- package/package/corpus/skills/extension-points/SKILL.md +248 -0
- package/package/corpus/skills/filter-syntax/LICENSE +23 -0
- package/package/corpus/skills/filter-syntax/NOTICE +17 -0
- package/package/corpus/skills/filter-syntax/SKILL.md +179 -0
- package/package/corpus/skills/including-generated-files/LICENSE +23 -0
- package/package/corpus/skills/including-generated-files/NOTICE +17 -0
- package/package/corpus/skills/including-generated-files/SKILL.md +139 -0
- package/package/corpus/skills/microbenchmarking/LICENSE +23 -0
- package/package/corpus/skills/microbenchmarking/NOTICE +36 -0
- package/package/corpus/skills/microbenchmarking/SKILL.md +131 -0
- package/package/corpus/skills/microbenchmarking/references/bdn-internals-and-tuning.md +143 -0
- package/package/corpus/skills/microbenchmarking/references/comparison-strategies.md +200 -0
- package/package/corpus/skills/microbenchmarking/references/diagnosers-and-exporters.md +150 -0
- package/package/corpus/skills/microbenchmarking/references/project-setup-and-running.md +189 -0
- package/package/corpus/skills/microbenchmarking/references/writing-benchmarks.md +310 -0
- package/package/corpus/skills/msbuild/LICENSE +23 -0
- package/package/corpus/skills/msbuild/NOTICE +55 -0
- package/package/corpus/skills/msbuild/SKILL.md +117 -0
- package/package/corpus/skills/msbuild/references/antipatterns/additional-antipatterns.md +291 -0
- package/package/corpus/skills/msbuild/references/antipatterns/incremental-build-inputs-outputs.md +57 -0
- package/package/corpus/skills/msbuild/references/antipatterns/private-assets.md +29 -0
- package/package/corpus/skills/msbuild/references/binlog-failure-analysis.md +85 -0
- package/package/corpus/skills/msbuild/references/binlog-generation.md +69 -0
- package/package/corpus/skills/msbuild/references/build-perf-baseline.md +493 -0
- package/package/corpus/skills/msbuild/references/build-perf-diagnostics.md +268 -0
- package/package/corpus/skills/msbuild/references/copy-to-output-directory.md +183 -0
- package/package/corpus/skills/msbuild/references/eval-performance.md +190 -0
- package/package/corpus/skills/msbuild/references/extension-points.md +281 -0
- package/package/corpus/skills/msbuild/references/incremental-build.md +365 -0
- package/package/corpus/skills/msbuild/references/msbuild-antipatterns.md +401 -0
- package/package/corpus/skills/orleans/LICENSE +21 -0
- package/package/corpus/skills/orleans/NOTICE +64 -0
- package/package/corpus/skills/orleans/SKILL.md +140 -0
- package/package/corpus/skills/orleans/references/anti-patterns.md +660 -0
- package/package/corpus/skills/orleans/references/configuration-api.md +933 -0
- package/package/corpus/skills/orleans/references/examples.md +66 -0
- package/package/corpus/skills/orleans/references/grain-api.md +784 -0
- package/package/corpus/skills/orleans/references/grains.md +75 -0
- package/package/corpus/skills/orleans/references/hosting.md +71 -0
- package/package/corpus/skills/orleans/references/implementation.md +591 -0
- package/package/corpus/skills/orleans/references/official-docs-index.md +250 -0
- package/package/corpus/skills/orleans/references/patterns.md +811 -0
- package/package/corpus/skills/orleans/references/persistence-api.md +495 -0
- package/package/corpus/skills/orleans/references/primitive-selection.md +35 -0
- package/package/corpus/skills/orleans/references/scheduling-and-services.md +295 -0
- package/package/corpus/skills/orleans/references/serialization-api.md +299 -0
- package/package/corpus/skills/orleans/references/streaming-api.md +396 -0
- package/package/corpus/skills/orleans/references/testing-patterns.md +210 -0
- package/package/corpus/skills/platform-detection/LICENSE +23 -0
- package/package/corpus/skills/platform-detection/NOTICE +17 -0
- package/package/corpus/skills/platform-detection/SKILL.md +230 -0
- package/package/corpus/skills/platform-detection/references/command-mode.md +27 -0
- package/package/corpus/skills/profiling/LICENSE +21 -0
- package/package/corpus/skills/profiling/NOTICE +50 -0
- package/package/corpus/skills/profiling/SKILL.md +144 -0
- package/package/corpus/skills/profiling/references/commands.md +439 -0
- package/package/corpus/skills/profiling/references/patterns.md +586 -0
- package/package/corpus/skills/profiling/references/profiling.md +190 -0
- package/package/corpus/skills/run-tests/LICENSE +23 -0
- package/package/corpus/skills/run-tests/NOTICE +19 -0
- package/package/corpus/skills/run-tests/SKILL.md +305 -0
- package/package/corpus/skills/target-authoring/LICENSE +23 -0
- package/package/corpus/skills/target-authoring/NOTICE +17 -0
- package/package/corpus/skills/target-authoring/SKILL.md +165 -0
- package/package/corpus/skills/vectorization/LICENSE +23 -0
- package/package/corpus/skills/vectorization/NOTICE +17 -0
- package/package/corpus/skills/vectorization/SKILL.md +189 -0
- package/package/profile-catalog.json +85 -1
- package/package.json +1 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Regex Patterns
|
|
2
|
+
|
|
3
|
+
### Choose the Right Regex Engine Mode
|
|
4
|
+
🟡 **DO** use `[GeneratedRegex]` for all static regex patterns, but never remove `NonBacktracking` if present | .NET 7+
|
|
5
|
+
|
|
6
|
+
❌
|
|
7
|
+
```csharp
|
|
8
|
+
var r = new Regex(dynamicPattern, RegexOptions.Compiled);
|
|
9
|
+
```
|
|
10
|
+
✅
|
|
11
|
+
```csharp
|
|
12
|
+
[GeneratedRegex("pattern")]
|
|
13
|
+
private static partial Regex MyRegex();
|
|
14
|
+
|
|
15
|
+
var safe = new Regex(untrustedPattern, RegexOptions.NonBacktracking);
|
|
16
|
+
|
|
17
|
+
var oneOff = new Regex("pattern");
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Impact: Source generator is always beneficial for static patterns. NonBacktracking prevents O(2^N) worst case — never remove it if present.**
|
|
21
|
+
|
|
22
|
+
### Use IsMatch When You Only Need a Boolean Result
|
|
23
|
+
🟡 **DO** use `IsMatch` instead of `Match(...).Success` | .NET 7+
|
|
24
|
+
|
|
25
|
+
❌
|
|
26
|
+
```csharp
|
|
27
|
+
bool found = Regex.Match(input, pattern).Success;
|
|
28
|
+
```
|
|
29
|
+
✅
|
|
30
|
+
```csharp
|
|
31
|
+
bool found = Regex.IsMatch(input, pattern);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Impact: Avoids Match object allocation; with NonBacktracking, ~3x faster by skipping capture computation.**
|
|
35
|
+
|
|
36
|
+
### Use Regex.Count/EnumerateMatches Instead of Matches
|
|
37
|
+
🟡 **DO** use `Count()` and `EnumerateMatches()` for allocation-free match processing | .NET 7+
|
|
38
|
+
|
|
39
|
+
❌
|
|
40
|
+
```csharp
|
|
41
|
+
int count = 0;
|
|
42
|
+
Match m = regex.Match(text);
|
|
43
|
+
while (m.Success) { count++; m = m.NextMatch(); }
|
|
44
|
+
```
|
|
45
|
+
✅
|
|
46
|
+
```csharp
|
|
47
|
+
int count = regex.Count(text);
|
|
48
|
+
|
|
49
|
+
foreach (ValueMatch m in Regex.EnumerateMatches(text, @"\b\w+\b"))
|
|
50
|
+
{
|
|
51
|
+
ReadOnlySpan<char> word = text.AsSpan(m.Index, m.Length);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Impact: ~3x faster than Match/NextMatch with NonBacktracking. Zero allocations for both Count and EnumerateMatches.**
|
|
56
|
+
|
|
57
|
+
### Use Span-Based Regex APIs for Allocation-Free Matching
|
|
58
|
+
🟡 **DO** use `ReadOnlySpan<char>` overloads for regex matching on spans | .NET 7+
|
|
59
|
+
|
|
60
|
+
❌
|
|
61
|
+
```csharp
|
|
62
|
+
string sub = largeBuffer.Substring(start, length);
|
|
63
|
+
bool found = Regex.IsMatch(sub, pattern);
|
|
64
|
+
```
|
|
65
|
+
✅
|
|
66
|
+
```csharp
|
|
67
|
+
ReadOnlySpan<char> text = largeBuffer.AsSpan(start, length);
|
|
68
|
+
foreach (ValueMatch m in Regex.EnumerateMatches(text, @"\b\w+\b"))
|
|
69
|
+
{
|
|
70
|
+
ReadOnlySpan<char> word = text.Slice(m.Index, m.Length);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Impact: Eliminates string allocations when working with spans — particularly valuable in high-throughput parsing pipelines.**
|
|
75
|
+
|
|
76
|
+
## Detection
|
|
77
|
+
|
|
78
|
+
Scan recipes for regex anti-patterns. Run these and report exact counts.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Compiled regex count (startup cost budget — compare ratio to GeneratedRegex)
|
|
82
|
+
grep -rn --include='*.cs' 'RegexOptions.Compiled' --exclude-dir=bin --exclude-dir=obj . | wc -l
|
|
83
|
+
|
|
84
|
+
# GeneratedRegex count (already optimized — verify the inverse)
|
|
85
|
+
grep -rn --include='*.cs' 'GeneratedRegex' --exclude-dir=bin --exclude-dir=obj . | wc -l
|
|
86
|
+
|
|
87
|
+
# Uncached new Regex() calls (construction cost per call)
|
|
88
|
+
grep -rn --include='*.cs' 'new Regex(' --exclude-dir=bin --exclude-dir=obj . | wc -l
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
When `RegexOptions.Compiled` appears inside a class constructor or field initializer of an instantiated class (not a static singleton), count how many instances of that class are created at startup to determine total compiled regex budget. For example, if a `Rule` class compiles a regex in its constructor and 122 rules are registered, that is 122 compiled regexes at startup.
|
|
92
|
+
|
|
93
|
+
### Patterns Requiring Manual Review
|
|
94
|
+
|
|
95
|
+
- **`new Regex(` uncached**: Field assignment may span multiple lines — grep on one line is unreliable. Verify that matched instances are stored in `static readonly` fields or `[GeneratedRegex]`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Structural Patterns
|
|
2
|
+
|
|
3
|
+
Patterns detected by the **absence** of a keyword or interface. These require codebase-wide counting scans, not single-file matching.
|
|
4
|
+
|
|
5
|
+
### Seal Classes for Devirtualization
|
|
6
|
+
🟡 **DO** seal all leaf classes (those not subclassed) | .NET Core 3.0+
|
|
7
|
+
|
|
8
|
+
Sealing lets the JIT devirtualize/inline virtual calls and use pointer comparison for type checks. Every non-abstract, non-static class that is not subclassed should be sealed. **Cratis qualification:** Never seal public types of a published framework/library package: doing so is a breaking change, and Cratis framework repositories treat public API changes as semver.
|
|
9
|
+
|
|
10
|
+
**Detection:** This is an absence pattern — scan for classes that are NOT sealed.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Count unsealed (non-abstract, non-static) classes
|
|
14
|
+
grep -rn --include='*.cs' -E '^\s*((public|internal|private|protected|file)\s+)?(partial\s+)?class ' --exclude-dir=bin --exclude-dir=obj . | grep -v 'sealed' | grep -v 'abstract' | grep -v 'static' | wc -l
|
|
15
|
+
|
|
16
|
+
# Count already-sealed classes (verify the inverse)
|
|
17
|
+
grep -rn --include='*.cs' 'sealed class' --exclude-dir=bin --exclude-dir=obj . | wc -l
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Exclusions:** Do not seal classes that are subclassed elsewhere in the codebase. Identifying base classes requires manual review — grep for `: ClassName` patterns and cross-reference, but expect false positives from interface implementations and generic constraints.
|
|
21
|
+
|
|
22
|
+
❌
|
|
23
|
+
```csharp
|
|
24
|
+
internal class MyHandler : Base
|
|
25
|
+
{ public override int Run() => 42; }
|
|
26
|
+
```
|
|
27
|
+
✅
|
|
28
|
+
```csharp
|
|
29
|
+
internal sealed class MyHandler : Base
|
|
30
|
+
{ public override int Run() => 42; }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Impact: Virtual calls up to 500x faster; type checks ~25x faster. Severity scales with count.**
|
|
34
|
+
|
|
35
|
+
**Scale-based severity:**
|
|
36
|
+
- 1-10 unsealed leaf classes → ℹ️ Info
|
|
37
|
+
- 11-50 unsealed leaf classes → 🟡 Moderate
|
|
38
|
+
- 50+ unsealed leaf classes → 🟡 Moderate (elevated priority)
|
|
@@ -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,22 @@
|
|
|
1
|
+
Generate Binary Logs
|
|
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-msbuild/skills/binlog-generation/SKILL.md
|
|
6
|
+
|
|
7
|
+
Changes made by Cratis:
|
|
8
|
+
|
|
9
|
+
LICENSE:
|
|
10
|
+
- Copy upstream MIT license and copyright verbatim.
|
|
11
|
+
|
|
12
|
+
SKILL.md:
|
|
13
|
+
- Remove the SDK version from the description; the 17.12 floor stays in the body.
|
|
14
|
+
- Normalize frontmatter serialization, add MIT license where absent; preserve name and description.
|
|
15
|
+
- Correct the binlog {} placeholder SDK/MSBuild minimum in description and body.
|
|
16
|
+
- Add marked modification/source comment and applicability/Cratis precedence line with the skill-specific safety, ownership or compatibility caveat.
|
|
17
|
+
- Render unimported binlog-failure-analysis routing reference as plain topic text.
|
|
18
|
+
- Render unimported build-perf-diagnostics routing reference as plain topic text.
|
|
19
|
+
- Correct the binlog {} placeholder SDK/MSBuild minimum.
|
|
20
|
+
- 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.
|
|
21
|
+
|
|
22
|
+
NOTICE: Add this attribution, change list, and any download/execution disclosure.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: binlog-generation
|
|
3
|
+
description: 'Generates MSBuild binary logs (binlogs) by adding /bl:{} to dotnet build, test, pack, publish, or restore commands, capturing a full build trace for later investigation. Use when a build error or build-performance problem needs a binlog and none exists. The {} placeholder needs a recent MSBuild; PowerShell must quote the switch as ''-bl:{}''. Not for analyzing an existing binlog or measuring build performance (use the msbuild skill) or for non-MSBuild build systems such as npm, Maven, or CMake.'
|
|
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/binlog-generation/SKILL.md; see NOTICE) -->
|
|
8
|
+
|
|
9
|
+
# Generate Binary Logs
|
|
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. Binlogs embed project and imported file contents: keep them local and task-scoped.
|
|
12
|
+
|
|
13
|
+
**Pass the `/bl` switch when running any MSBuild-based command.** This is a non-negotiable requirement for all .NET builds.
|
|
14
|
+
|
|
15
|
+
## Commands That Require /bl
|
|
16
|
+
|
|
17
|
+
You MUST add the `/bl:{}` flag to:
|
|
18
|
+
- `dotnet build`
|
|
19
|
+
- `dotnet test`
|
|
20
|
+
- `dotnet pack`
|
|
21
|
+
- `dotnet publish`
|
|
22
|
+
- `dotnet restore`
|
|
23
|
+
- `msbuild` or `msbuild.exe`
|
|
24
|
+
- Any other command that invokes MSBuild
|
|
25
|
+
|
|
26
|
+
## Preferred: Use `{}` for Automatic Unique Names
|
|
27
|
+
|
|
28
|
+
> **Note:** The `{}` placeholder requires MSBuild 17.12+ / .NET 9.0.100 SDK or later.
|
|
29
|
+
|
|
30
|
+
The `{}` placeholder in the binlog filename is replaced by MSBuild with a unique identifier, guaranteeing no two builds ever overwrite each other — without needing to track or check existing files.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Every invocation produces a distinct file automatically
|
|
34
|
+
dotnet build /bl:{}
|
|
35
|
+
dotnet test /bl:{}
|
|
36
|
+
dotnet build --configuration Release /bl:{}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**PowerShell requires quoting the complete switch:**
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
# Keep the literal {} placeholder in one argument
|
|
43
|
+
dotnet build '-bl:{}'
|
|
44
|
+
dotnet test '-bl:{}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Why This Matters
|
|
48
|
+
|
|
49
|
+
1. **Unique names prevent overwrites** - You can always go back and analyze previous builds
|
|
50
|
+
2. **Failure analysis** - When a build fails, the binlog is already there for immediate analysis
|
|
51
|
+
3. **Comparison** - You can compare builds before and after changes
|
|
52
|
+
4. **No re-running builds** - You never need to re-run a failed build just to generate a binlog
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# ✅ CORRECT - {} generates a unique name automatically (bash/cmd)
|
|
58
|
+
dotnet build /bl:{}
|
|
59
|
+
dotnet test /bl:{}
|
|
60
|
+
|
|
61
|
+
# ✅ CORRECT - quote the complete PowerShell argument
|
|
62
|
+
dotnet build '-bl:{}'
|
|
63
|
+
dotnet test '-bl:{}'
|
|
64
|
+
|
|
65
|
+
# ❌ WRONG - Missing /bl flag entirely
|
|
66
|
+
dotnet build
|
|
67
|
+
dotnet test
|
|
68
|
+
|
|
69
|
+
# ❌ WRONG - No filename (overwrites the same msbuild.binlog every time)
|
|
70
|
+
dotnet build /bl
|
|
71
|
+
dotnet build /bl
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## One build = one binlog
|
|
75
|
+
|
|
76
|
+
Add `/bl:{}` to **every** MSBuild invocation separately — never reuse a name and
|
|
77
|
+
never rely on bare `/bl`:
|
|
78
|
+
|
|
79
|
+
- Building several configurations, projects, or retrying a failed build? Each
|
|
80
|
+
command still gets its own `/bl:{}` so the logs never overwrite each other.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
dotnet build -c Debug /bl:{} # unique file
|
|
84
|
+
dotnet build -c Release /bl:{} # another unique file
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Verify the binlog exists
|
|
88
|
+
|
|
89
|
+
After the build, confirm a `.binlog` was actually produced before moving on to
|
|
90
|
+
analysis — a build that fails *before* MSBuild starts (e.g. a bad argument)
|
|
91
|
+
writes no binlog:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
ls -1 *.binlog # bash
|
|
95
|
+
dir /b *.binlog # Windows cmd
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
Get-ChildItem *.binlog # PowerShell
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Note the resulting path so binlog failure analysis or build perf diagnostics
|
|
103
|
+
can consume it.
|
|
104
|
+
|
|
105
|
+
## When a Specific Filename Is Required
|
|
106
|
+
|
|
107
|
+
If the binlog filename needs to be known upfront (e.g., for CI artifact upload), or if `{}` is not available in the installed MSBuild version, pick a name that won't collide with existing files:
|
|
108
|
+
|
|
109
|
+
1. Check for existing `*.binlog` files in the directory
|
|
110
|
+
2. Choose a name not already taken (e.g., by incrementing a counter from the highest existing number)
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Example: directory contains 3.binlog — use 4.binlog
|
|
114
|
+
dotnet build /bl:4.binlog
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Cleaning the Repository
|
|
118
|
+
|
|
119
|
+
When cleaning the repository with `git clean`, **always exclude binlog files** to preserve your build history:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# ✅ CORRECT - Exclude binlog files from cleaning
|
|
123
|
+
git clean -fdx -e "*.binlog"
|
|
124
|
+
|
|
125
|
+
# ❌ WRONG - This deletes binlog files (they're usually in .gitignore)
|
|
126
|
+
git clean -fdx
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
This is especially important when iterating on build fixes - you need the binlogs to analyze what changed between builds.
|
|
@@ -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,27 @@
|
|
|
1
|
+
Detecting OutputPath and IntermediateOutputPath Clashes
|
|
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-msbuild/skills/check-bin-obj-clash/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.
|
|
15
|
+
- Render unimported msbuild-antipatterns routing reference as plain topic text.
|
|
16
|
+
- Replace the blanket BuildProjectReferences=false exclusion with an evidence-based metadata-only query qualification.
|
|
17
|
+
- Qualify the structured workflow exclusion by actual targets and writes.
|
|
18
|
+
- Qualify the text-replay exclusion by actual targets and writes.
|
|
19
|
+
- Move the complete ## Common Causes and Fixes section verbatim into references/common-causes-and-fixes.md to fit the body limit; leave a direct pointer.
|
|
20
|
+
- 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.
|
|
21
|
+
- Point the antipatterns cross-references at the bundled msbuild skill reference.
|
|
22
|
+
|
|
23
|
+
references/common-causes-and-fixes.md:
|
|
24
|
+
- Contain the section moved verbatim from SKILL.md, with a reference H1 title.
|
|
25
|
+
- Add or normalize the top Contents list from existing headings; preserve section content.
|
|
26
|
+
|
|
27
|
+
NOTICE: Add this attribution, change list, and any download/execution disclosure.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: check-bin-obj-clash
|
|
3
|
+
description: 'Detects MSBuild projects with conflicting OutputPath or IntermediateOutputPath and fixes the clash. Use when builds fail with ''Cannot create a file when that file already exists'' or ''The process cannot access the file because it is being used by another process'', fail intermittently but pass on retry, or overwrite outputs in multi-project or multi-targeting builds where bin/obj or project.assets.json collide. Not for OS-level file locking, single-project single-TFM builds, or non-MSBuild build 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/check-bin-obj-clash/SKILL.md; see NOTICE) -->
|
|
8
|
+
|
|
9
|
+
# Detecting OutputPath and IntermediateOutputPath Clashes
|
|
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
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
This skill helps identify when multiple MSBuild project evaluations share the same `OutputPath` or `IntermediateOutputPath`. This is a common source of build failures including:
|
|
16
|
+
|
|
17
|
+
- File access conflicts during parallel builds
|
|
18
|
+
- Missing or overwritten output files
|
|
19
|
+
- Intermittent build failures
|
|
20
|
+
- "File in use" errors
|
|
21
|
+
- **NuGet restore errors like `Cannot create a file when that file already exists`** - this strongly indicates multiple projects share the same `IntermediateOutputPath` where `project.assets.json` is written
|
|
22
|
+
|
|
23
|
+
Clashes can occur between:
|
|
24
|
+
- **Different projects** sharing the same output directory
|
|
25
|
+
- **Multi-targeting builds** (e.g., `TargetFrameworks=net8.0;net9.0`) where the path doesn't include the target framework
|
|
26
|
+
- **Multiple solution builds** where the same project is built from different solutions in a single build
|
|
27
|
+
|
|
28
|
+
**Cratis qualification:** `BuildProjectReferences=false` only suppresses building referenced projects; it does not prove that this project instance is read-only. Exclude an instance only when its actual targets and writes show a metadata-only query (for example, `GetTargetPath`).
|
|
29
|
+
|
|
30
|
+
## When to Use This Skill
|
|
31
|
+
|
|
32
|
+
**Invoke this skill immediately when you see:**
|
|
33
|
+
- `Cannot create a file when that file already exists` during NuGet restore
|
|
34
|
+
- `The process cannot access the file because it is being used by another process`
|
|
35
|
+
- Intermittent build failures that succeed on retry
|
|
36
|
+
- Missing output files or unexpected overwriting
|
|
37
|
+
|
|
38
|
+
## Step 1: Generate a Binary Log
|
|
39
|
+
|
|
40
|
+
Use the `binlog-generation` skill to generate a binary log with the correct naming convention.
|
|
41
|
+
|
|
42
|
+
## Primary workflow — binlog MCP
|
|
43
|
+
|
|
44
|
+
The MCP server exposes structured tools for inspecting a `.binlog` without
|
|
45
|
+
parsing text logs. Call them directly instead of replaying the binlog to a text
|
|
46
|
+
file. Call `tools/list` for the MCP first if you are unsure which tools are available.
|
|
47
|
+
|
|
48
|
+
**Important constraints:**
|
|
49
|
+
- The `.binlog` file is a **binary format** — do NOT try to `cat`, `head`, `strings`, or read it directly. Use only the MCP tools to query it.
|
|
50
|
+
- **Synthesize findings as you go.** Do not spend all available time investigating — once you have enough evidence, present your conclusions.
|
|
51
|
+
|
|
52
|
+
### Step 2: Get an overview and list projects
|
|
53
|
+
|
|
54
|
+
Use the MCP overview and projects tools to understand the build and list all projects that participated.
|
|
55
|
+
|
|
56
|
+
### Step 3: Check evaluations and global properties
|
|
57
|
+
|
|
58
|
+
Use the MCP `evaluations` and `evaluation_global_properties` tools to find all evaluations per project. Look for:
|
|
59
|
+
- Multiple evaluations for the same project (indicates multi-targeting or multiple build configurations)
|
|
60
|
+
- Differing global properties between evaluations (`TargetFramework`, `Configuration`, `RuntimeIdentifier`, `SolutionFileName`, `PublishReadyToRun`, etc.)
|
|
61
|
+
|
|
62
|
+
### Step 4: Get output paths for each evaluation
|
|
63
|
+
|
|
64
|
+
Use the MCP properties tool to query `OutputPath`, `IntermediateOutputPath`, `BaseOutputPath`, and `BaseIntermediateOutputPath` for each project evaluation.
|
|
65
|
+
|
|
66
|
+
### Step 5: Check for double writes
|
|
67
|
+
|
|
68
|
+
Use the MCP double_writes tool if available — it directly detects files written by multiple project instances.
|
|
69
|
+
|
|
70
|
+
### Step 6: Identify clashes
|
|
71
|
+
|
|
72
|
+
Compare the `OutputPath` and `IntermediateOutputPath` values across all evaluations:
|
|
73
|
+
1. **Normalize paths** - Convert to absolute paths and normalize separators
|
|
74
|
+
2. **Group by path** - Find evaluations that share the same OutputPath or IntermediateOutputPath
|
|
75
|
+
3. **Filter out non-build evaluations** - Exclude only instances proven by their targets and writes to be metadata-only queries; `BuildProjectReferences=false` alone is insufficient.
|
|
76
|
+
4. **Report clashes** - Any group with more than one evaluation indicates a clash
|
|
77
|
+
|
|
78
|
+
## Fallback workflow — text-log replay (when MCP is unavailable)
|
|
79
|
+
|
|
80
|
+
Use this only when the MCP server cannot be started.
|
|
81
|
+
|
|
82
|
+
Replay the binlog to a diagnostic text log, then grep for the same signals the MCP tools surface:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
dotnet msbuild build.binlog -noconlog -fl "-flp:v=diag;logfile=full.log"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then extract the clash signals:
|
|
89
|
+
|
|
90
|
+
- **Projects & evaluations** — list evaluation starts and count them per project: `grep 'Evaluation started' full.log | grep -oiE '"[^"]+\.[a-z]+proj"' | sort | uniq -c`. Matching the full **quoted path** keeps same-named projects in different directories distinct (and tolerates spaces in paths); a path with a count ≥ 2 was evaluated more than once (multi-targeting or extra global properties). (`grep -c` alone only totals evaluations across the whole log, so it can't reveal per-project duplication.)
|
|
91
|
+
- **Output paths** — `grep -iE 'OutputPath[[:space:]]*=|IntermediateOutputPath[[:space:]]*=|BaseOutputPath[[:space:]]*=|BaseIntermediateOutputPath[[:space:]]*=' full.log | sort -u`, or query a project directly: `dotnet msbuild MyProject.csproj -getProperty:OutputPath` (and `IntermediateOutputPath`, `BaseIntermediateOutputPath`).
|
|
92
|
+
- **Distinguishing global properties** — `grep -iE 'TargetFramework|Configuration|Platform|RuntimeIdentifier|SolutionFileName|PublishReadyToRun' full.log`. See the [Global Properties to Check](references/common-causes-and-fixes.md#global-properties-to-check-when-comparing-evaluations) table for which affect the path and which just fork a redundant instance.
|
|
93
|
+
- **Corroborating evidence (optional)** — `grep 'Target "CopyFilesToOutputDirectory"' full.log` plus `grep 'SkipUnchangedFiles' full.log` show a second instance writing (or skipping a masked write) to the same path; a long vs ~0 ms `CoreCompile` distinguishes the real build from a redundant instance.
|
|
94
|
+
|
|
95
|
+
**Then identify clashes:** normalize paths to absolute, group evaluations by `OutputPath` and by `IntermediateOutputPath`, and exclude only instances proven by their targets and writes to be metadata-only queries, not merely marked `BuildProjectReferences=false` — plus, for `OutputPath` only, `MSBuildRestoreSessionId` restore evaluations. Any group with more than one remaining evaluation is a clash.
|
|
96
|
+
|
|
97
|
+
Read references/common-causes-and-fixes.md when selecting the relevant diagnostic workflow.
|
|
98
|
+
|
|
99
|
+
## Tips
|
|
100
|
+
|
|
101
|
+
- The SDK default paths include `$(TargetFramework)` — clashes often occur when projects override these defaults; normalize relative paths to absolute before comparing.
|
|
102
|
+
- **Cross-project `IntermediateOutputPath` clashes cannot be fixed with `AppendTargetFrameworkToOutputPath`** — files like `project.assets.json` are written directly to the intermediate path. For multi-targeting clashes *within the same project*, `AppendTargetFrameworkToOutputPath=true` is the correct fix.
|
|
103
|
+
- Error messages that indicate a path clash: `Cannot create a file when that file already exists` (NuGet restore), `The process cannot access the file because it is being used by another process`, or intermittent failures that succeed on retry.
|
|
104
|
+
|
|
105
|
+
### Global Properties to Check When Comparing Evaluations
|
|
106
|
+
|
|
107
|
+
When multiple evaluations share an output path, compare these global properties to understand why:
|
|
108
|
+
|
|
109
|
+
| Property | Affects OutputPath? | Notes |
|
|
110
|
+
|----------|---------------------|-------|
|
|
111
|
+
| `TargetFramework` | Yes | Different TFMs should have different paths. **Exception:** re-injecting a *single-targeting* project's own TFM (e.g. via `SetTargetFramework` with the same value) is path-neutral — it forks a redundant instance sharing the output path (see "`SetTargetFramework` re-injecting...") |
|
|
112
|
+
| `RuntimeIdentifier` | Yes | Different RIDs should have different paths |
|
|
113
|
+
| `Configuration` | Yes | Debug vs Release |
|
|
114
|
+
| `Platform` | Yes | AnyCPU vs x64 etc. |
|
|
115
|
+
| `SolutionFileName` | No | Identifies which solution built the project — different values indicate multi-solution clash |
|
|
116
|
+
| `SolutionName` | No | Solution name without extension |
|
|
117
|
+
| `SolutionPath` | No | Full path to the solution file |
|
|
118
|
+
| `SolutionDir` | No | Directory containing the solution file |
|
|
119
|
+
| `CurrentSolutionConfigurationContents` | No | XML with project entries — count of entries reveals which solution |
|
|
120
|
+
| `BuildProjectReferences` | No | `false` = P2P query, not a real build - ignore these |
|
|
121
|
+
| `MSBuildRestoreSessionId` | No | Present = restore phase evaluation |
|
|
122
|
+
| `PublishReadyToRun` | No | Publish setting, doesn't change build output path but creates distinct project instances |
|
|
123
|
+
| `_IsPublishing` | No | Publish flag; an `<MSBuild>` Build/Publish call with this set (in this project or another that consumes it) forks a publish instance sharing the build output path (see "Explicit `<MSBuild>` Build/Publish with extra global properties") |
|
|
124
|
+
|
|
125
|
+
## Testing Fixes
|
|
126
|
+
|
|
127
|
+
After making changes to fix path clashes, clean and rebuild to verify. See the `binlog-generation` skill's "Cleaning the Repository" section on how to clean the repository while preserving binlog files.
|