@cratis/pi 7.101.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/github-actions.instructions.md +17 -0
- 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/github-actions.md +17 -0
- 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/cratis-ci-pipeline-performance/LICENSE +2 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/SKILL.md +201 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/build-once-and-shard.md +158 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/caching.md +86 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/flaky-and-hung-jobs.md +70 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/publish-pipelines.md +67 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/required-checks-and-path-filters.md +117 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/runner-sizing-and-images.md +65 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/security-and-pinning.md +73 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/sources.md +33 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/references/test-setup-cost.md +82 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/scripts/ci-timings.sh +356 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/scripts/fixtures/jobs/1003.json +79 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/scripts/fixtures/jobs/1007.json +79 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/scripts/fixtures/jobs/1010.json +79 -0
- package/package/corpus/skills/cratis-ci-pipeline-performance/scripts/fixtures/runs.json +102 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/LICENSE +2 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/SKILL.md +244 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/docker-images.md +86 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/dotnet-nuget.md +87 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/go-jvm-python-elixir.md +83 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/npm-yarn.md +78 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/other-environments.md +60 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/references/worked-examples.md +97 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/scripts/cratis-local-packages.sh +778 -0
- package/package/corpus/skills/cratis-engineering-local-cross-repo-verification/scripts/npm-restore-check.cjs +109 -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 +87 -1
- package/package.json +3 -2
|
@@ -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.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Output-path clash causes and fixes
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Common Causes and Fixes
|
|
6
|
+
- Multi-targeting without TargetFramework in path
|
|
7
|
+
- Shared output directory across projects (CANNOT be fixed with AppendTargetFramework)
|
|
8
|
+
- RuntimeIdentifier builds clashing
|
|
9
|
+
- Multiple solutions building the same project
|
|
10
|
+
- Extra global properties creating redundant project instances
|
|
11
|
+
- Explicit `<MSBuild>` Build/Publish with extra global properties (self or cross-project)
|
|
12
|
+
- `SetTargetFramework` re-injecting a single-targeting project's own TFM on a `ProjectReference`
|
|
13
|
+
|
|
14
|
+
## Common Causes and Fixes
|
|
15
|
+
|
|
16
|
+
### Multi-targeting without TargetFramework in path
|
|
17
|
+
|
|
18
|
+
**Problem:** Project uses `TargetFrameworks` but OutputPath doesn't vary by framework.
|
|
19
|
+
|
|
20
|
+
```xml
|
|
21
|
+
<!-- BAD: Same path for all frameworks -->
|
|
22
|
+
<OutputPath>bin\$(Configuration)\</OutputPath>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Fix:** Include TargetFramework in the path:
|
|
26
|
+
|
|
27
|
+
```xml
|
|
28
|
+
<!-- GOOD: Path varies by framework -->
|
|
29
|
+
<OutputPath>bin\$(Configuration)\$(TargetFramework)\</OutputPath>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or rely on SDK defaults which handle this automatically:
|
|
33
|
+
|
|
34
|
+
```xml
|
|
35
|
+
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
|
|
36
|
+
<AppendTargetFrameworkToIntermediateOutputPath>true</AppendTargetFrameworkToIntermediateOutputPath>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Shared output directory across projects (CANNOT be fixed with AppendTargetFramework)
|
|
40
|
+
|
|
41
|
+
**Problem:** Multiple projects explicitly set the same `BaseOutputPath` or `BaseIntermediateOutputPath`.
|
|
42
|
+
|
|
43
|
+
```xml
|
|
44
|
+
<!-- Project A - Directory.Build.props -->
|
|
45
|
+
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
|
|
46
|
+
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>
|
|
47
|
+
|
|
48
|
+
<!-- Project B - Directory.Build.props -->
|
|
49
|
+
<BaseOutputPath>..\SharedOutput\</BaseOutputPath>
|
|
50
|
+
<BaseIntermediateOutputPath>..\SharedObj\</BaseIntermediateOutputPath>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**IMPORTANT:** Even with `AppendTargetFrameworkToOutputPath=true`, this will still clash! .NET writes certain files directly to the `IntermediateOutputPath` without the TargetFramework suffix, including:
|
|
54
|
+
|
|
55
|
+
- `project.assets.json` (NuGet restore output)
|
|
56
|
+
- Other NuGet-related files
|
|
57
|
+
|
|
58
|
+
This causes errors like `Cannot create a file when that file already exists` during parallel restore.
|
|
59
|
+
|
|
60
|
+
**Fix:** Each project MUST have a unique `BaseIntermediateOutputPath`. Do not share intermediate output directories across projects:
|
|
61
|
+
|
|
62
|
+
```xml
|
|
63
|
+
<!-- Project A -->
|
|
64
|
+
<BaseIntermediateOutputPath>..\obj\ProjectA\</BaseIntermediateOutputPath>
|
|
65
|
+
|
|
66
|
+
<!-- Project B -->
|
|
67
|
+
<BaseIntermediateOutputPath>..\obj\ProjectB\</BaseIntermediateOutputPath>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or simply use the SDK defaults which place `obj` inside each project's directory.
|
|
71
|
+
|
|
72
|
+
### RuntimeIdentifier builds clashing
|
|
73
|
+
|
|
74
|
+
**Problem:** Building for multiple RIDs without RID in path.
|
|
75
|
+
|
|
76
|
+
**Fix:** Ensure RuntimeIdentifier is in the path:
|
|
77
|
+
|
|
78
|
+
```xml
|
|
79
|
+
<AppendRuntimeIdentifierToOutputPath>true</AppendRuntimeIdentifierToOutputPath>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Multiple solutions building the same project
|
|
83
|
+
|
|
84
|
+
**Problem:** A single build invokes multiple solutions (e.g., via MSBuild task or command line) that include the same project. Each solution build evaluates and builds the project independently, with different `Solution*` global properties that don't affect the output path.
|
|
85
|
+
|
|
86
|
+
**How to detect:** Compare `SolutionFileName` and `CurrentSolutionConfigurationContents` across evaluations for the same project. Different values indicate multi-solution builds. For example:
|
|
87
|
+
|
|
88
|
+
| Property | Eval from Solution A | Eval from Solution B |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `SolutionFileName` | `BuildAnalyzers.sln` | `Main.slnx` |
|
|
91
|
+
| `CurrentSolutionConfigurationContents` | 1 project entry | ~49 project entries |
|
|
92
|
+
| `OutputPath` | `bin\Release\netstandard2.0\` | `bin\Release\netstandard2.0\` ← **clash** |
|
|
93
|
+
|
|
94
|
+
**Example:** A repo build script builds `BuildAnalyzers.sln` then `Main.slnx`, and both solutions include `SharedAnalyzers.csproj`. Both builds write to `bin\Release\netstandard2.0\`. The first build compiles; the second skips compilation but still runs `CopyFilesToOutputDirectory`.
|
|
95
|
+
|
|
96
|
+
**Fix:** Options include:
|
|
97
|
+
1. **Consolidate solutions** - Ensure each project is only built from one solution in a single build
|
|
98
|
+
2. **Use different configurations** - Build solutions with different `Configuration` values that result in different output paths
|
|
99
|
+
3. **Exclude duplicate projects** - Use solution filters or conditional project inclusion to avoid building the same project twice
|
|
100
|
+
|
|
101
|
+
### Extra global properties creating redundant project instances
|
|
102
|
+
|
|
103
|
+
**Problem:** A project is built multiple times within the same solution due to extra global properties (e.g., `PublishReadyToRun=false`) that create distinct MSBuild project instances. These properties don't affect output paths but prevent MSBuild from caching results across instances, causing redundant target execution.
|
|
104
|
+
|
|
105
|
+
**How to detect:** Compare global properties across evaluations for the same project within the same solution (same `SolutionFileName`). Look for properties that differ but don't contribute to path differentiation:
|
|
106
|
+
|
|
107
|
+
| Property | Eval A (from Razor.slnx) | Eval B (from Razor.slnx) |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `PublishReadyToRun` | *(not set)* | `false` |
|
|
110
|
+
| `OutputPath` | `bin\Release\netstandard2.0\` | `bin\Release\netstandard2.0\` ← **clash** |
|
|
111
|
+
|
|
112
|
+
This is particularly wasteful for projects where the extra property has no effect (e.g., `PublishReadyToRun` on a `netstandard2.0` class library that doesn't use ReadyToRun compilation).
|
|
113
|
+
|
|
114
|
+
**Fix:** Options include:
|
|
115
|
+
1. **Remove the extra global property** - Investigate which parent target/task is injecting the property and prevent it from being passed to projects that don't need it
|
|
116
|
+
2. **Use `RemoveGlobalProperties` metadata** - On `ProjectReference` items, use `RemoveGlobalProperties="PublishReadyToRun"` to strip the property before building the referenced project
|
|
117
|
+
3. **Condition the property** - Only set the property on projects that actually use it (e.g., only for executable projects, not class libraries)
|
|
118
|
+
|
|
119
|
+
### Explicit `<MSBuild>` Build/Publish with extra global properties (self or cross-project)
|
|
120
|
+
|
|
121
|
+
**Problem:** A target uses the `<MSBuild>` task to build or publish a project with an extra global property, most commonly a "publish-on-build" target. The offending call can be in the target project itself **or in another project** that consumes it (e.g. a test or layout project publishing a tool):
|
|
122
|
+
|
|
123
|
+
```xml
|
|
124
|
+
<!-- (a) same project (publish-on-build) -->
|
|
125
|
+
<Target Name="PublishOnBuild" AfterTargets="Build">
|
|
126
|
+
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Publish" Properties="_IsPublishing=true" />
|
|
127
|
+
</Target>
|
|
128
|
+
|
|
129
|
+
<!-- (b) project A publishes project B that it consumes -->
|
|
130
|
+
<MSBuild Projects="..\tool\tool.csproj" Targets="Publish" Properties="_IsPublishing=true" />
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Either way this forks a distinct instance of the target project (`path` + `{_IsPublishing=true}`) that shares the same `OutputPath`/`IntermediateOutputPath` as the instance the solution/graph already builds. Both write the same files — for NativeAOT this includes the `*.sourcelink` intermediate, which produces `SourceLinkWriter` / "file in use" failures under parallel builds.
|
|
134
|
+
|
|
135
|
+
**How to detect:** Follow the Primary workflow above — the `evaluations` and `evaluation_global_properties` tools surface two evaluations of the target project that share the same `OutputPath`/`IntermediateOutputPath` but differ only by a path-neutral publish flag such as `_IsPublishing`, and the `double_writes` tool flags the resulting shared-file writes directly. To tell case (a) from (b), see which project the extra `{_IsPublishing=true}` evaluation runs *under* in the build tree (from the overview/projects tools): the target project itself for (a), or a consumer project that invoked the `<MSBuild>` task for (b).
|
|
136
|
+
|
|
137
|
+
**Fix:** Depends on where the call lives:
|
|
138
|
+
|
|
139
|
+
- **Same project (a):** you can't strip the property with `RemoveGlobalProperties` (the project injects it on itself). Set the flag as a **static** (non-global) property and run the target in the **same** instance via `DependsOnTargets`/`CallTarget`, with a guard against a target cycle when publish is the entry point:
|
|
140
|
+
|
|
141
|
+
```xml
|
|
142
|
+
<PropertyGroup>
|
|
143
|
+
<_PublishWasInvokedDirectly Condition="'$(_IsPublishing)' == 'true'">true</_PublishWasInvokedDirectly>
|
|
144
|
+
<_IsPublishing>true</_IsPublishing>
|
|
145
|
+
</PropertyGroup>
|
|
146
|
+
<Target Name="PublishOnBuild"
|
|
147
|
+
AfterTargets="Build"
|
|
148
|
+
DependsOnTargets="Publish"
|
|
149
|
+
Condition="'$(_PublishWasInvokedDirectly)' != 'true'" />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- **Cross-project (b):** the consumer must not fork the producer with path-neutral global properties. Make the producer publish as part of its own build (the (a) fix in *its* project), then have the consumer **sequence** it and read its output instead of re-publishing it:
|
|
153
|
+
|
|
154
|
+
```xml
|
|
155
|
+
<ItemGroup>
|
|
156
|
+
<ProjectReference Include="..\tool\tool.csproj" ReferenceOutputAssembly="false" />
|
|
157
|
+
</ItemGroup>
|
|
158
|
+
<!-- consumer reads tool's publish dir; it does NOT invoke Publish on tool -->
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
See `msbuild` skill `references/msbuild-antipatterns.md` (AP-22) for the authoring-time smell and rationale.
|
|
162
|
+
|
|
163
|
+
### `SetTargetFramework` re-injecting a single-targeting project's own TFM on a `ProjectReference`
|
|
164
|
+
|
|
165
|
+
**Problem:** A `ProjectReference` sets `SetTargetFramework="TargetFramework=<tfm>"` metadata pointing at a **single-targeting** project (one that uses singular `<TargetFramework>`, not `<TargetFrameworks>`), where the injected `<tfm>` **equals the TFM the project already targets**. `SetTargetFramework` injects `TargetFramework` as a **global property** on the referenced project's build.
|
|
166
|
+
|
|
167
|
+
```xml
|
|
168
|
+
<!-- BAD: Tool.csproj single-targets net8.0 and we inject that SAME net8.0 -->
|
|
169
|
+
<ProjectReference Include="..\Tool\Tool.csproj" SetTargetFramework="TargetFramework=net8.0" />
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Injecting the TFM the project already targets is **path-neutral** — the project already resolves to `bin\<config>\net8.0\` and `obj\<config>\net8.0\` on its own. So it doesn't change the output path; it only forks a distinct instance `(project, {TargetFramework=net8.0})`. The solution/graph builds the very same project as `(project, {})`. Both share the same `OutputPath`/`IntermediateOutputPath`, so the project is **built twice** to the same location — a bin/obj clash under parallel builds.
|
|
173
|
+
|
|
174
|
+
**How to detect:** Follow the Primary workflow above. The `evaluations` and `evaluation_global_properties` tools surface two evaluations of the referenced project that share the same `OutputPath`/`IntermediateOutputPath` and differ only by a `TargetFramework` global property, while the project itself is single-targeting (its own `TargetFramework` already equals the injected value). The `double_writes` tool flags the resulting shared-file writes directly.
|
|
175
|
+
|
|
176
|
+
**Note:** The P2P protocol itself does **not** inject `TargetFramework` for a non-multi-targeting reference — the clash comes specifically from the explicit `SetTargetFramework` metadata overriding that safe default.
|
|
177
|
+
|
|
178
|
+
**Fix:** Remove the redundant `SetTargetFramework` when it just restates the project's own single TFM:
|
|
179
|
+
|
|
180
|
+
```xml
|
|
181
|
+
<!-- GOOD -->
|
|
182
|
+
<ProjectReference Include="..\Tool\Tool.csproj" />
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**When `SetTargetFramework` is legitimate (not a clash):**
|
|
186
|
+
|
|
187
|
+
- **Multi-targeting reference** — the referenced project uses `<TargetFrameworks>` and you need one specific TFM. Each TFM has a distinct output path, so no clash.
|
|
188
|
+
- **Overriding to a *different* TFM** — you may use `SetTargetFramework` on a single-targeting project to build it under a TFM *other than* the one it declares. Because the injected TFM then changes the output path (`obj\<config>\<different-tfm>\`), the instance no longer collides with `(project, {})`. Only the *same-TFM* case is path-neutral and clashing.
|
|
189
|
+
- **Framework-incompatible reference** — whenever the referencing and referenced projects target **incompatible frameworks** (e.g. a `.NETFramework` project referencing a `.NETCoreApp` project, or vice-versa) — **regardless of single- or multi-targeting on either side** — set `SkipGetTargetFrameworkProperties="true"` (the P2P `GetTargetFrameworkProperties` negotiation would otherwise fail) and `ReferenceOutputAssembly="false"` (an assembly built for an incompatible framework can't be consumed as a reference — you only want to trigger/sequence the build):
|
|
190
|
+
|
|
191
|
+
```xml
|
|
192
|
+
<ProjectReference Include="..\Tool\Tool.csproj"
|
|
193
|
+
SkipGetTargetFrameworkProperties="true"
|
|
194
|
+
ReferenceOutputAssembly="false" />
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
With `SkipGetTargetFrameworkProperties="true"`, the negotiation no longer stops the **referencing** project's own `TargetFramework` global property (present when it builds for a specific TFM, e.g. it is multi-targeting) from flowing into the referenced project. For a **single-targeting** referenced project that would force it to build under the wrong TFM / output path. Prevent it by either setting `SetTargetFramework="TargetFramework=<tfm>"` (pin the TFM) **or** `UndefineProperties="TargetFramework"` (strip the inherited global property so the project builds as it declares) — use one, not both:
|
|
198
|
+
|
|
199
|
+
```xml
|
|
200
|
+
<ProjectReference Include="..\Tool\Tool.csproj"
|
|
201
|
+
SkipGetTargetFrameworkProperties="true"
|
|
202
|
+
UndefineProperties="TargetFramework"
|
|
203
|
+
ReferenceOutputAssembly="false" />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
See `msbuild` skill `references/msbuild-antipatterns.md` (AP-23) for the authoring-time smell and rationale.
|
|
@@ -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,32 @@
|
|
|
1
|
+
Coverage Analysis
|
|
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-test/skills/coverage-analysis/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
|
+
- Render unimported find-untested-sources routing reference as plain topic text.
|
|
16
|
+
- Render unimported test-gap-analysis routing reference as plain topic text.
|
|
17
|
+
- Render unimported test-tagging routing reference as plain topic text.
|
|
18
|
+
- Render unimported crap-score routing reference as plain topic text.
|
|
19
|
+
- Add direct conditional pointers for all otherwise-indirect reference/script/asset files: scripts/Compute-CrapScores.ps1, scripts/CoverageData.ps1, scripts/Extract-MethodCoverage.ps1.
|
|
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
|
+
- Remove references to sibling skills that are not part of this corpus.
|
|
22
|
+
|
|
23
|
+
references/report-generation.md:
|
|
24
|
+
- Prefix official tool downloads/installs with marked approval/pinned-version guidance and privileged/perfcollect examples with explicit root/container-security approval, where present.
|
|
25
|
+
|
|
26
|
+
references/setup-discovery.md:
|
|
27
|
+
- Add or normalize the top Contents list from existing headings; preserve section content.
|
|
28
|
+
|
|
29
|
+
NOTICE: Add this attribution, change list, and any download/execution disclosure.
|
|
30
|
+
|
|
31
|
+
Executes or downloads (instructions retained, not executed by this import):
|
|
32
|
+
- references/report-generation.md: dotnet tool install dotnet-reportgenerator-globaltool --tool-path $rgToolPath
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coverage-analysis
|
|
3
|
+
description: 'Interprets supplied .NET coverage reports (Cobertura, line, branch, condition metrics) or collects coverage on request: partial conditions, plateaus, target arithmetic, project-wide coverage-backed CRAP, and refactoring safety. Use when coverage reports, percentages, or an explicit coverage-collection request are present. Analyzes supplied reports directly without rerunning tests or installing tools. Not for requests with no coverage evidence, hypothetical change-survival questions, CRAP for one named target, writing tests (use cratis-specifications-csharp), or running tests (use run-tests).'
|
|
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-test/skills/coverage-analysis/SKILL.md; see NOTICE) -->
|
|
8
|
+
|
|
9
|
+
# Coverage Analysis
|
|
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. The C# and Python pairing scripts differ on `.Spec`/`.Specs` project suffixes; Cratis specification projects end in `.Specs`. Coverage is not behavior evidence.
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
Explain what .NET coverage evidence proves, reconcile target arithmetic, and
|
|
16
|
+
identify the code blocking progress. Add complexity/CRAP ranking only when the
|
|
17
|
+
user explicitly asks for risk hotspots, CRAP, priorities by risk, or refactoring
|
|
18
|
+
safety.
|
|
19
|
+
|
|
20
|
+
## When to Use
|
|
21
|
+
|
|
22
|
+
Use this skill for interpreting supplied .NET line/branch/condition evidence,
|
|
23
|
+
coverage gaps and plateaus, target arithmetic, or explicit project-wide
|
|
24
|
+
coverage-backed risk analysis.
|
|
25
|
+
|
|
26
|
+
## When Not to Use
|
|
27
|
+
|
|
28
|
+
- **Named method, class, or file CRAP/refactoring-safety analysis** — out of scope; analyze that target directly
|
|
29
|
+
- **Static source-to-test pairing or listing files with no tests** — out of scope
|
|
30
|
+
- **Behavioral or pseudo-mutation gaps in existing tests** — out of scope
|
|
31
|
+
- **Test trait/category distributions or coverage shape by test type** — out of scope
|
|
32
|
+
- **Writing or generating tests** — this skill identifies where tests are needed, not write them
|
|
33
|
+
- **General test execution** unrelated to coverage or CRAP analysis
|
|
34
|
+
- **Only collecting .NET coverage or printing a raw percentage with no diagnosis** — use `run-tests`; use native tooling for non-.NET coverage collection or analysis. Interpreting .NET line/branch gaps remains in scope here
|
|
35
|
+
|
|
36
|
+
## Inputs
|
|
37
|
+
|
|
38
|
+
| Input | Required | Default | Description |
|
|
39
|
+
|-------|----------|---------|-------------|
|
|
40
|
+
| Project/solution path | No | Current directory | Path to the .NET solution or project |
|
|
41
|
+
| Line coverage threshold | No | 80% | Minimum acceptable line coverage |
|
|
42
|
+
| Branch coverage threshold | No | 70% | Minimum acceptable branch coverage |
|
|
43
|
+
| Existing Cobertura path | No | Discover only if not supplied | Preferred input; never rerun tests when usable |
|
|
44
|
+
| CRAP threshold | No | 30 | Used only for explicit risk/CRAP requests |
|
|
45
|
+
| Hotspot count | No | 3 | Explicit risk requests only; cap at 10 unless the user asks for more |
|
|
46
|
+
|
|
47
|
+
Discover optional inputs from the workspace. Do not ask for a project path when
|
|
48
|
+
the current directory or a supplied report is sufficient.
|
|
49
|
+
|
|
50
|
+
## Choose the smallest matching path
|
|
51
|
+
|
|
52
|
+
| User intent | Required work | Do not do |
|
|
53
|
+
|-------------|---------------|-----------|
|
|
54
|
+
| Explain a supplied excerpt, condition, or summary | Answer directly from the supplied evidence | Tools, CRAP, discovery, report files |
|
|
55
|
+
| Interpret a supplied Cobertura path or diagnose a plateau | Read that report, reconcile totals, name all material gaps, answer directly | Rerun tests, install tools, compute CRAP, or generate files unless explicitly requested |
|
|
56
|
+
| Rank risk hotspots, compute project-wide CRAP, or assess refactoring safety | Use the supplied/existing report, read `references/guidelines.md`, and compute CRAP before ranking | Coverage-only ranking or a full report template unless requested |
|
|
57
|
+
| Analyze coverage when no report exists | Invoke `run-tests` to collect coverage with the repository-compatible runner, then analyze the generated report | Choose or execute a test command independently; CRAP unless risk was requested |
|
|
58
|
+
| Produce a full markdown/HTML/CSV report | First deliver the direct answer; then read `references/output-format.md` or `references/report-generation.md` | Report generation before the answer |
|
|
59
|
+
|
|
60
|
+
Words such as **analyze coverage**, **what is blocking coverage**, or **why is
|
|
61
|
+
coverage stuck** do not by themselves request CRAP. Explicit signals include
|
|
62
|
+
**risk hotspot**, **CRAP**, **complexity-weighted priority**, **safe to refactor**,
|
|
63
|
+
or an equivalent request to combine complexity with coverage.
|
|
64
|
+
|
|
65
|
+
## Existing-data fast path
|
|
66
|
+
|
|
67
|
+
When the user supplies a coverage excerpt, summary, or valid Cobertura path:
|
|
68
|
+
|
|
69
|
+
- Treat it as authoritative input and start there.
|
|
70
|
+
- Do not discover the solution or test projects unless source mapping is necessary.
|
|
71
|
+
- Do not run `dotnet test`, install ReportGenerator, add a coverage package, or
|
|
72
|
+
read `references/setup-discovery.md` or `references/report-generation.md`.
|
|
73
|
+
- Do not write `coverage-analysis.md` or create a report directory unless the user
|
|
74
|
+
requested a saved/full report.
|
|
75
|
+
- For interpretation and plateau questions, parse only the evidence needed to
|
|
76
|
+
answer. For explicit project-wide risk requests, use the bundled scripts as
|
|
77
|
+
described in `references/guidelines.md`.
|
|
78
|
+
|
|
79
|
+
A failed read/view operation is not proof that a named path does not exist.
|
|
80
|
+
Classify the failure, then make one targeted existence probe and use a normalized
|
|
81
|
+
path or alternate reader only for confirmed tool availability, transport, or
|
|
82
|
+
path-normalization failures and only after verifying the canonical path remains
|
|
83
|
+
inside the workspace. Stop on content-exclusion, permission/policy,
|
|
84
|
+
workspace-boundary, or unknown failures. Report a missing path only when the
|
|
85
|
+
independent probe also fails; do not broaden the search or substitute another
|
|
86
|
+
artifact.
|
|
87
|
+
|
|
88
|
+
## Collection path
|
|
89
|
+
|
|
90
|
+
Use this path only when no usable coverage evidence exists and the user asked for
|
|
91
|
+
analysis that requires it.
|
|
92
|
+
|
|
93
|
+
1. Read `references/setup-discovery.md`.
|
|
94
|
+
2. Prefer existing Cobertura discovered under the requested root.
|
|
95
|
+
3. If none exists, invoke `run-tests` for repository overlay, platform, runner,
|
|
96
|
+
and command selection, and have it collect Cobertura once per entry point.
|
|
97
|
+
4. Analyze the resulting Cobertura. Compute CRAP only if risk analysis was
|
|
98
|
+
explicitly requested.
|
|
99
|
+
|
|
100
|
+
When the workspace contains the project/test manifests needed by this path,
|
|
101
|
+
perform discovery directly and delegate collection to `run-tests`. Do not ask
|
|
102
|
+
the user to attach files or pre-run coverage that the current workspace lets
|
|
103
|
+
you inspect and generate.
|
|
104
|
+
|
|
105
|
+
Do not modify production code. Any incidental test-project change needed for
|
|
106
|
+
collection is owned by `run-tests`; include that change and its revert command
|
|
107
|
+
in the final analysis.
|
|
108
|
+
|
|
109
|
+
The automatic collection path is for SDK-style projects. For classic non-SDK or
|
|
110
|
+
`packages.config` projects, use only a repository-owned coverage command. If none
|
|
111
|
+
exists, stop and request Cobertura XML. Never migrate the project, inject an
|
|
112
|
+
SDK-style provider, create a wrapper project, or report substitute coverage from
|
|
113
|
+
another assembly.
|
|
114
|
+
|
|
115
|
+
## Interpretation and arithmetic invariants
|
|
116
|
+
|
|
117
|
+
- A line hit proves execution, not both decision outcomes.
|
|
118
|
+
- `condition-coverage="50% (1/2)"` proves one reported outcome ran, but not which
|
|
119
|
+
one. Recommend forcing the opposite outcome. Without source, never invent likely
|
|
120
|
+
predicates or claim whether true or false is missing. State that compound
|
|
121
|
+
predicates need independently exercised operands and short-circuit combinations
|
|
122
|
+
when applicable; do not infer the exact combinations without source or fuller XML.
|
|
123
|
+
- Derive overall totals from Cobertura's covered/valid line counts. For target
|
|
124
|
+
`T`, required covered lines are `ceiling(valid lines × T)`.
|
|
125
|
+
- Projected coverage is `(current covered lines + newly covered distinct lines) /
|
|
126
|
+
valid lines`. State assumptions such as fully covering a method.
|
|
127
|
+
- When asked whether one member can reach a target, show its maximum projected
|
|
128
|
+
total and at least one concrete sufficient combination of supplied members or
|
|
129
|
+
line gains. If no supplied combination is sufficient, say so.
|
|
130
|
+
- For a multi-member target, name the exact combination and resulting covered /
|
|
131
|
+
valid total; saying only "combine it with another member" is incomplete.
|
|
132
|
+
- Reconcile member gaps against project totals. Method line ranges can overlap or
|
|
133
|
+
omit class-level lines, so do not sum method counts as project truth.
|
|
134
|
+
- Never call one member the **sole**, **entire**, or **all** remaining gap unless
|
|
135
|
+
its distinct uncovered lines exactly reconcile with the project total and no
|
|
136
|
+
other below-threshold member remains.
|
|
137
|
+
- Name every supplied or extracted below-threshold member, but keep detail
|
|
138
|
+
proportional: lead with the blockers, summarize the remainder in one sentence
|
|
139
|
+
or a compact table.
|
|
140
|
+
|
|
141
|
+
## Response contract
|
|
142
|
+
|
|
143
|
+
Answer the user's question in the first 2–4 sentences.
|
|
144
|
+
|
|
145
|
+
- **Excerpt or arithmetic question:** one explanation plus the next test or member
|
|
146
|
+
priority. No dashboard.
|
|
147
|
+
- **Existing-report interpretation or plateau:** overall line/branch coverage,
|
|
148
|
+
blocking members, reconciled target impact, and 1–3 recommendations. Use at
|
|
149
|
+
most one compact table.
|
|
150
|
+
- **Explicit risk/CRAP request:** top 3 actual hotspots by default, supporting
|
|
151
|
+
complexity/coverage/CRAP values, remaining flagged count, and 1–3 priorities.
|
|
152
|
+
Exclude fully covered low-risk methods from the hotspot table. Never exceed 10
|
|
153
|
+
rows unless the user requests a larger count. For refactoring safety, rank risky
|
|
154
|
+
methods by CRAP rather than raw coverage alone, then name comparatively safe
|
|
155
|
+
well-covered methods separately.
|
|
156
|
+
- **Explicit full report request:** read `references/output-format.md`. Save the
|
|
157
|
+
report only then.
|
|
158
|
+
|
|
159
|
+
Report only artifacts that exist. Do not announce inaccessible output paths or
|
|
160
|
+
failed optional file writes when no file was requested.
|
|
161
|
+
|
|
162
|
+
## Optional reports
|
|
163
|
+
|
|
164
|
+
HTML/CSV/markdown files are not part of normal analysis. Generate them only when
|
|
165
|
+
the user explicitly requests report files or a CI artifact.
|
|
166
|
+
|
|
167
|
+
1. Deliver the direct coverage/risk answer first.
|
|
168
|
+
2. For a full markdown report, read `references/output-format.md` and save it.
|
|
169
|
+
3. For HTML/CSV, then read `references/report-generation.md`. Do not install
|
|
170
|
+
ReportGenerator before the direct answer, and do not retry a failed install.
|
|
171
|
+
|
|
172
|
+
## Validation
|
|
173
|
+
|
|
174
|
+
- Confirm a supplied report was used without test execution or tool installation.
|
|
175
|
+
- Reconcile covered, valid, and uncovered line totals before projecting impact.
|
|
176
|
+
- Confirm every stated blocker comes from supplied or extracted evidence.
|
|
177
|
+
- If CRAP was requested, spot-check one score using `references/guidelines.md`.
|
|
178
|
+
- If files were requested, verify they exist before reporting their paths.
|
|
179
|
+
|
|
180
|
+
## Common Pitfalls
|
|
181
|
+
|
|
182
|
+
- **Existing report triggers setup work** — stop. Analyze the named artifact first.
|
|
183
|
+
- **Generic analysis triggers CRAP** — stop. CRAP requires explicit risk intent.
|
|
184
|
+
- **One method is called the entire gap** — reconcile distinct uncovered lines and
|
|
185
|
+
the full below-threshold set first.
|
|
186
|
+
- **A small request gets a dashboard** — scale down to a direct answer or one table.
|
|
187
|
+
- **No Cobertura from collection** — report the collection failure; do not invent
|
|
188
|
+
substitute coverage.
|
|
189
|
+
- **Compiler-generated method names** — verify suspicious async, lambda, or local
|
|
190
|
+
function names against source before presenting them as user-authored members.
|
|
191
|
+
- **Test exit code 1** — coverage may still exist; proceed with a warning. Other
|
|
192
|
+
nonzero build failures stop the collection path.
|
|
193
|
+
|
|
194
|
+
## Reference navigation
|
|
195
|
+
|
|
196
|
+
- Read scripts/Compute-CrapScores.ps1 when working on Compute CrapScores.
|
|
197
|
+
- Read scripts/CoverageData.ps1 when working on CoverageData.
|
|
198
|
+
- Read scripts/Extract-MethodCoverage.ps1 when working on Extract MethodCoverage.
|