[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M699CSVZ0H8A0CDKK73EEJDG":3,"skill-same:01M699CSVZ0H8A0CDKK73EEJDG":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":48,"linkOnly":49,"markdownContent":50,"markdownBody":51,"frontMatter":52,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":6,"ownerHtmlUrl":58,"ownerBlogUrl":59,"ownerDescription":60,"updatedAt":61,"install":62,"resources":75},"01M699CSVZ0H8A0CDKK73EEJDG","check-bin-obj-clash",null,"Find OutputPath\u002FIntermediateOutputPath collisions between distinct projects or required property\u002FTFM variants. USE FOR: missing\u002Foverwritten bin\u002Fobj or project.assets.json, parallel 'Cannot create a file when that file already exists' or 'file is being used by another process', shared paths, missing AppendTargetFrameworkToOutputPath, PublishReadyToRun, SetTargetFramework on single-target references. DO NOT USE FOR: duplicates or invariant-generation races (find-repeated-work-within-one-build), OS locking, single-instance builds, non-MSBuild systems.","microsoft\u002Ftestfx","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M699C71CJ91B5WZ3AXG3GG2M",1059,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fcheck-bin-obj-clash\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47],"OBJ","check","check bin obj clash","create","use","single","missing","for","do","parallel","os","paths","work","references","when","variants","project","duplicates","projects","shared","file access","2026-11-10 10:12:30",false,"---\nname: check-bin-obj-clash\ndescription: \"Find OutputPath\u002FIntermediateOutputPath collisions between distinct projects or required property\u002FTFM variants. USE FOR: missing\u002Foverwritten bin\u002Fobj or project.assets.json, parallel 'Cannot create a file when that file already exists' or 'file is being used by another process', shared paths, missing AppendTargetFrameworkToOutputPath, PublishReadyToRun, SetTargetFramework on single-target references. DO NOT USE FOR: duplicates or invariant-generation races (find-repeated-work-within-one-build), OS locking, single-instance builds, non-MSBuild systems.\"\nlicense: MIT\n---\n\n# Detecting OutputPath and IntermediateOutputPath Clashes\n\n## Overview\n\nThis skill helps identify when multiple MSBuild project evaluations share the same `OutputPath` or `IntermediateOutputPath`. This is a common source of build failures including:\n\n- File access conflicts during parallel builds\n- Missing or overwritten output files\n- Intermittent build failures\n- \"File in use\" errors\n- **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\n\nClashes can occur between:\n- **Different projects** sharing the same output directory\n- **Multi-targeting builds** (e.g., `TargetFrameworks=net8.0;net9.0`) where the path doesn't include the target framework\n- **Multiple solution builds** where the same project is built from different solutions in a single build\n\n**Note:** Project instances with `BuildProjectReferences=false` should be **ignored** when analyzing clashes - these are P2P reference resolution builds that only query metadata (via `GetTargetPath`) and do not actually write to output directories.\n\n## When to Use This Skill\n\n**Invoke this skill immediately when you see:**\n- `Cannot create a file when that file already exists` during NuGet restore\n- `The process cannot access the file because it is being used by another process`\n- Intermittent build failures that succeed on retry\n- Missing output files or unexpected overwriting\n\n## Step 1: Generate a Binary Log\n\nUse the `binlog-generation` skill to generate a binary log with the correct naming convention.\n\n## Primary workflow — binlog MCP\n\nThe MCP server exposes structured tools for inspecting a `.binlog` without\nparsing text logs. Call them directly instead of replaying the binlog to a text\nfile. Call `tools\u002Flist` for the MCP first if you are unsure which tools are available.\n\n**Important constraints:**\n- 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.\n- **Synthesize findings as you go.** Do not spend all available time investigating — once you have enough evidence, present your conclusions.\n\n### Step 2: Get an overview and list projects\n\nUse the MCP overview and projects tools to understand the build and list all projects that participated.\n\n### Step 3: Check evaluations and global properties\n\nUse the MCP `evaluations` and `evaluation_global_properties` tools to find all evaluations per project. Look for:\n- Multiple evaluations for the same project (indicates multi-targeting or multiple build configurations)\n- Differing global properties between evaluations (`TargetFramework`, `Configuration`, `RuntimeIdentifier`, `SolutionFileName`, `PublishReadyToRun`, etc.)\n\n### Step 4: Get output paths for each evaluation\n\nUse the MCP properties tool to query `OutputPath`, `IntermediateOutputPath`, `BaseOutputPath`, and `BaseIntermediateOutputPath` for each project evaluation.\n\n### Step 5: Check for double writes\n\nUse the MCP double_writes tool if available — it directly detects files written by multiple project instances.\n\n### Step 6: Identify clashes\n\nCompare the `OutputPath` and `IntermediateOutputPath` values across all evaluations:\n1. **Normalize paths** - Convert to absolute paths and normalize separators\n2. **Group by path** - Find evaluations that share the same OutputPath or IntermediateOutputPath\n3. **Filter out non-build evaluations** - Exclude `BuildProjectReferences=false` instances (P2P queries)\n4. **Report clashes** - Any group with more than one evaluation indicates a clash\n\n## Fallback workflow — text-log replay (when MCP is unavailable)\n\nUse this only when the MCP server cannot be started.\n\nReplay the binlog to a diagnostic text log, then grep for the same signals the MCP tools surface:\n\n```bash\ndotnet msbuild build.binlog -noconlog -fl \"-flp:v=diag;logfile=full.log\"\n```\n\nThen extract the clash signals:\n\n- **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.)\n- **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`).\n- **Distinguishing global properties** — `grep -iE 'TargetFramework|Configuration|Platform|RuntimeIdentifier|SolutionFileName|PublishReadyToRun' full.log`. See the [Global Properties to Check](#global-properties-to-check-when-comparing-evaluations) table for which affect the path and which just fork a redundant instance.\n- **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.\n\n**Then identify clashes:** normalize paths to absolute, group evaluations by `OutputPath` and by `IntermediateOutputPath`, and exclude `BuildProjectReferences=false` (P2P queries) — plus, for `OutputPath` only, `MSBuildRestoreSessionId` restore evaluations. Any group with more than one remaining evaluation is a clash.\n\n## Common Causes and Fixes\n\n### Multi-targeting without TargetFramework in path\n\n**Problem:** Project uses `TargetFrameworks` but OutputPath doesn't vary by framework.\n\n```xml\n\u003C!-- BAD: Same path for all frameworks -->\n\u003COutputPath>bin\\$(Configuration)\\\u003C\u002FOutputPath>\n```\n\n**Fix:** Include TargetFramework in the path:\n\n```xml\n\u003C!-- GOOD: Path varies by framework -->\n\u003COutputPath>bin\\$(Configuration)\\$(TargetFramework)\\\u003C\u002FOutputPath>\n```\n\nOr rely on SDK defaults which handle this automatically:\n\n```xml\n\u003CAppendTargetFrameworkToOutputPath>true\u003C\u002FAppendTargetFrameworkToOutputPath>\n\u003CAppendTargetFrameworkToIntermediateOutputPath>true\u003C\u002FAppendTargetFrameworkToIntermediateOutputPath>\n```\n\n### Shared output directory across projects (CANNOT be fixed with AppendTargetFramework)\n\n**Problem:** Multiple projects explicitly set the same `BaseOutputPath` or `BaseIntermediateOutputPath`.\n\n```xml\n\u003C!-- Project A - Directory.Build.props -->\n\u003CBaseOutputPath>..\\SharedOutput\\\u003C\u002FBaseOutputPath>\n\u003CBaseIntermediateOutputPath>..\\SharedObj\\\u003C\u002FBaseIntermediateOutputPath>\n\n\u003C!-- Project B - Directory.Build.props -->\n\u003CBaseOutputPath>..\\SharedOutput\\\u003C\u002FBaseOutputPath>\n\u003CBaseIntermediateOutputPath>..\\SharedObj\\\u003C\u002FBaseIntermediateOutputPath>\n```\n\n**IMPORTANT:** Even with `AppendTargetFrameworkToOutputPath=true`, this will still clash! .NET writes certain files directly to the `IntermediateOutputPath` without the TargetFramework suffix, including:\n\n- `project.assets.json` (NuGet restore output)\n- Other NuGet-related files\n\nThis causes errors like `Cannot create a file when that file already exists` during parallel restore.\n\n**Fix:** Each project MUST have a unique `BaseIntermediateOutputPath`. Do not share intermediate output directories across projects:\n\n```xml\n\u003C!-- Project A -->\n\u003CBaseIntermediateOutputPath>..\\obj\\ProjectA\\\u003C\u002FBaseIntermediateOutputPath>\n\n\u003C!-- Project B -->\n\u003CBaseIntermediateOutputPath>..\\obj\\ProjectB\\\u003C\u002FBaseIntermediateOutputPath>\n```\n\nOr simply use the SDK defaults which place `obj` inside each project's directory.\n\n### RuntimeIdentifier builds clashing\n\n**Problem:** Building for multiple RIDs without RID in path.\n\n**Fix:** Ensure RuntimeIdentifier is in the path:\n\n```xml\n\u003CAppendRuntimeIdentifierToOutputPath>true\u003C\u002FAppendRuntimeIdentifierToOutputPath>\n```\n\n### Multiple solutions building the same project\n\n**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.\n\n**How to detect:** Compare `SolutionFileName` and `CurrentSolutionConfigurationContents` across evaluations for the same project. Different values indicate multi-solution builds. For example:\n\n| Property | Eval from Solution A | Eval from Solution B |\n|---|---|---|\n| `SolutionFileName` | `BuildAnalyzers.sln` | `Main.slnx` |\n| `CurrentSolutionConfigurationContents` | 1 project entry | ~49 project entries |\n| `OutputPath` | `bin\\Release\\netstandard2.0\\` | `bin\\Release\\netstandard2.0\\` ← **clash** |\n\n**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`.\n\n**Fix:** Options include:\n1. **Consolidate solutions** - Ensure each project is only built from one solution in a single build\n2. **Use different configurations** - Build solutions with different `Configuration` values that result in different output paths\n3. **Exclude duplicate projects** - Use solution filters or conditional project inclusion to avoid building the same project twice\n\n### Extra global properties creating redundant project instances\n\n**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.\n\n**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:\n\n| Property | Eval A (from Razor.slnx) | Eval B (from Razor.slnx) |\n|---|---|---|\n| `PublishReadyToRun` | *(not set)* | `false` |\n| `OutputPath` | `bin\\Release\\netstandard2.0\\` | `bin\\Release\\netstandard2.0\\` ← **clash** |\n\nThis 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).\n\n**Fix:** Options include:\n1. **Remove the extra global property** - Investigate which parent target\u002Ftask is injecting the property and prevent it from being passed to projects that don't need it\n2. **Use `RemoveGlobalProperties` metadata** - On `ProjectReference` items, use `RemoveGlobalProperties=\"PublishReadyToRun\"` to strip the property before building the referenced project\n3. **Condition the property** - Only set the property on projects that actually use it (e.g., only for executable projects, not class libraries)\n\n### Explicit `\u003CMSBuild>` Build\u002FPublish with extra global properties (self or cross-project)\n\n**Problem:** A target uses the `\u003CMSBuild>` 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):\n\n```xml\n\u003C!-- (a) same project (publish-on-build) -->\n\u003CTarget Name=\"PublishOnBuild\" AfterTargets=\"Build\">\n  \u003CMSBuild Projects=\"$(MSBuildProjectFullPath)\" Targets=\"Publish\" Properties=\"_IsPublishing=true\" \u002F>\n\u003C\u002FTarget>\n\n\u003C!-- (b) project A publishes project B that it consumes -->\n\u003CMSBuild Projects=\"..\\tool\\tool.csproj\" Targets=\"Publish\" Properties=\"_IsPublishing=true\" \u002F>\n```\n\nEither way this forks a distinct instance of the target project (`path` + `{_IsPublishing=true}`) that shares the same `OutputPath`\u002F`IntermediateOutputPath` as the instance the solution\u002Fgraph already builds. Both write the same files — for NativeAOT this includes the `*.sourcelink` intermediate, which produces `SourceLinkWriter` \u002F \"file in use\" failures under parallel builds.\n\n**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`\u002F`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\u002Fprojects tools): the target project itself for (a), or a consumer project that invoked the `\u003CMSBuild>` task for (b).\n\n**Fix:** Depends on where the call lives:\n\n- **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`\u002F`CallTarget`, with a guard against a target cycle when publish is the entry point:\n\n```xml\n\u003CPropertyGroup>\n  \u003C_PublishWasInvokedDirectly Condition=\"'$(_IsPublishing)' == 'true'\">true\u003C\u002F_PublishWasInvokedDirectly>\n  \u003C_IsPublishing>true\u003C\u002F_IsPublishing>\n\u003C\u002FPropertyGroup>\n\u003CTarget Name=\"PublishOnBuild\"\n        AfterTargets=\"Build\"\n        DependsOnTargets=\"Publish\"\n        Condition=\"'$(_PublishWasInvokedDirectly)' != 'true'\" \u002F>\n```\n\n- **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:\n\n```xml\n\u003CItemGroup>\n  \u003CProjectReference Include=\"..\\tool\\tool.csproj\" ReferenceOutputAssembly=\"false\" \u002F>\n\u003C\u002FItemGroup>\n\u003C!-- consumer reads tool's publish dir; it does NOT invoke Publish on tool -->\n```\n\nSee the `msbuild-antipatterns` skill (AP-22) for the authoring-time smell and rationale.\n\n### `SetTargetFramework` re-injecting a single-targeting project's own TFM on a `ProjectReference`\n\n**Problem:** A `ProjectReference` sets `SetTargetFramework=\"TargetFramework=\u003Ctfm>\"` metadata pointing at a **single-targeting** project (one that uses singular `\u003CTargetFramework>`, not `\u003CTargetFrameworks>`), where the injected `\u003Ctfm>` **equals the TFM the project already targets**. `SetTargetFramework` injects `TargetFramework` as a **global property** on the referenced project's build.\n\n```xml\n\u003C!-- BAD: Tool.csproj single-targets net8.0 and we inject that SAME net8.0 -->\n\u003CProjectReference Include=\"..\\Tool\\Tool.csproj\" SetTargetFramework=\"TargetFramework=net8.0\" \u002F>\n```\n\nInjecting the TFM the project already targets is **path-neutral** — the project already resolves to `bin\\\u003Cconfig>\\net8.0\\` and `obj\\\u003Cconfig>\\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\u002Fgraph builds the very same project as `(project, {})`. Both share the same `OutputPath`\u002F`IntermediateOutputPath`, so the project is **built twice** to the same location — a bin\u002Fobj clash under parallel builds.\n\n**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`\u002F`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.\n\n**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.\n\n**Fix:** Remove the redundant `SetTargetFramework` when it just restates the project's own single TFM:\n\n```xml\n\u003C!-- GOOD -->\n\u003CProjectReference Include=\"..\\Tool\\Tool.csproj\" \u002F>\n```\n\n**When `SetTargetFramework` is legitimate (not a clash):**\n\n- **Multi-targeting reference** — the referenced project uses `\u003CTargetFrameworks>` and you need one specific TFM. Each TFM has a distinct output path, so no clash.\n- **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\\\u003Cconfig>\\\u003Cdifferent-tfm>\\`), the instance no longer collides with `(project, {})`. Only the *same-TFM* case is path-neutral and clashing.\n- **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\u002Fsequence the build):\n\n  ```xml\n  \u003CProjectReference Include=\"..\\Tool\\Tool.csproj\"\n                    SkipGetTargetFrameworkProperties=\"true\"\n                    ReferenceOutputAssembly=\"false\" \u002F>\n  ```\n\n  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 \u002F output path. Prevent it by either setting `SetTargetFramework=\"TargetFramework=\u003Ctfm>\"` (pin the TFM) **or** `UndefineProperties=\"TargetFramework\"` (strip the inherited global property so the project builds as it declares) — use one, not both:\n\n  ```xml\n  \u003CProjectReference Include=\"..\\Tool\\Tool.csproj\"\n                    SkipGetTargetFrameworkProperties=\"true\"\n                    UndefineProperties=\"TargetFramework\"\n                    ReferenceOutputAssembly=\"false\" \u002F>\n  ```\n\nSee the `msbuild-antipatterns` skill (AP-23) for the authoring-time smell and rationale.\n\n## Tips\n\n- The SDK default paths include `$(TargetFramework)` — clashes often occur when projects override these defaults; normalize relative paths to absolute before comparing.\n- **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.\n- 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.\n\n### Global Properties to Check When Comparing Evaluations\n\nWhen multiple evaluations share an output path, compare these global properties to understand why:\n\n| Property | Affects OutputPath? | Notes |\n|----------|---------------------|-------|\n| `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...\") |\n| `RuntimeIdentifier` | Yes | Different RIDs should have different paths |\n| `Configuration` | Yes | Debug vs Release |\n| `Platform` | Yes | AnyCPU vs x64 etc. |\n| `SolutionFileName` | No | Identifies which solution built the project — different values indicate multi-solution clash |\n| `SolutionName` | No | Solution name without extension |\n| `SolutionPath` | No | Full path to the solution file |\n| `SolutionDir` | No | Directory containing the solution file |\n| `CurrentSolutionConfigurationContents` | No | XML with project entries — count of entries reveals which solution |\n| `BuildProjectReferences` | No | `false` = P2P query, not a real build - ignore these |\n| `MSBuildRestoreSessionId` | No | Present = restore phase evaluation |\n| `PublishReadyToRun` | No | Publish setting, doesn't change build output path but creates distinct project instances |\n| `_IsPublishing` | No | Publish flag; an `\u003CMSBuild>` Build\u002FPublish call with this set (in this project or another that consumes it) forks a publish instance sharing the build output path (see \"Explicit `\u003CMSBuild>` Build\u002FPublish with extra global properties\") |\n\n## Testing Fixes\n\nAfter 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.\n","# Detecting OutputPath and IntermediateOutputPath Clashes\n\n## Overview\n\nThis skill helps identify when multiple MSBuild project evaluations share the same `OutputPath` or `IntermediateOutputPath`. This is a common source of build failures including:\n\n- File access conflicts during parallel builds\n- Missing or overwritten output files\n- Intermittent build failures\n- \"File in use\" errors\n- **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\n\nClashes can occur between:\n- **Different projects** sharing the same output directory\n- **Multi-targeting builds** (e.g., `TargetFrameworks=net8.0;net9.0`) where the path doesn't include the target framework\n- **Multiple solution builds** where the same project is built from different solutions in a single build\n\n**Note:** Project instances with `BuildProjectReferences=false` should be **ignored** when analyzing clashes - these are P2P reference resolution builds that only query metadata (via `GetTargetPath`) and do not actually write to output directories.\n\n## When to Use This Skill\n\n**Invoke this skill immediately when you see:**\n- `Cannot create a file when that file already exists` during NuGet restore\n- `The process cannot access the file because it is being used by another process`\n- Intermittent build failures that succeed on retry\n- Missing output files or unexpected overwriting\n\n## Step 1: Generate a Binary Log\n\nUse the `binlog-generation` skill to generate a binary log with the correct naming convention.\n\n## Primary workflow — binlog MCP\n\nThe MCP server exposes structured tools for inspecting a `.binlog` without\nparsing text logs. Call them directly instead of replaying the binlog to a text\nfile. Call `tools\u002Flist` for the MCP first if you are unsure which tools are available.\n\n**Important constraints:**\n- 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.\n- **Synthesize findings as you go.** Do not spend all available time investigating — once you have enough evidence, present your conclusions.\n\n### Step 2: Get an overview and list projects\n\nUse the MCP overview and projects tools to understand the build and list all projects that participated.\n\n### Step 3: Check evaluations and global properties\n\nUse the MCP `evaluations` and `evaluation_global_properties` tools to find all evaluations per project. Look for:\n- Multiple evaluations for the same project (indicates multi-targeting or multiple build configurations)\n- Differing global properties between evaluations (`TargetFramework`, `Configuration`, `RuntimeIdentifier`, `SolutionFileName`, `PublishReadyToRun`, etc.)\n\n### Step 4: Get output paths for each evaluation\n\nUse the MCP properties tool to query `OutputPath`, `IntermediateOutputPath`, `BaseOutputPath`, and `BaseIntermediateOutputPath` for each project evaluation.\n\n### Step 5: Check for double writes\n\nUse the MCP double_writes tool if available — it directly detects files written by multiple project instances.\n\n### Step 6: Identify clashes\n\nCompare the `OutputPath` and `IntermediateOutputPath` values across all evaluations:\n1. **Normalize paths** - Convert to absolute paths and normalize separators\n2. **Group by path** - Find evaluations that share the same OutputPath or IntermediateOutputPath\n3. **Filter out non-build evaluations** - Exclude `BuildProjectReferences=false` instances (P2P queries)\n4. **Report clashes** - Any group with more than one evaluation indicates a clash\n\n## Fallback workflow — text-log replay (when MCP is unavailable)\n\nUse this only when the MCP server cannot be started.\n\nReplay the binlog to a diagnostic text log, then grep for the same signals the MCP tools surface:\n\n```bash\ndotnet msbuild build.binlog -noconlog -fl \"-flp:v=diag;logfile=full.log\"\n```\n\nThen extract the clash signals:\n\n- **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.)\n- **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`).\n- **Distinguishing global properties** — `grep -iE 'TargetFramework|Configuration|Platform|RuntimeIdentifier|SolutionFileName|PublishReadyToRun' full.log`. See the [Global Properties to Check](#global-properties-to-check-when-comparing-evaluations) table for which affect the path and which just fork a redundant instance.\n- **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.\n\n**Then identify clashes:** normalize paths to absolute, group evaluations by `OutputPath` and by `IntermediateOutputPath`, and exclude `BuildProjectReferences=false` (P2P queries) — plus, for `OutputPath` only, `MSBuildRestoreSessionId` restore evaluations. Any group with more than one remaining evaluation is a clash.\n\n## Common Causes and Fixes\n\n### Multi-targeting without TargetFramework in path\n\n**Problem:** Project uses `TargetFrameworks` but OutputPath doesn't vary by framework.\n\n```xml\n\u003C!-- BAD: Same path for all frameworks -->\n\u003COutputPath>bin\\$(Configuration)\\\u003C\u002FOutputPath>\n```\n\n**Fix:** Include TargetFramework in the path:\n\n```xml\n\u003C!-- GOOD: Path varies by framework -->\n\u003COutputPath>bin\\$(Configuration)\\$(TargetFramework)\\\u003C\u002FOutputPath>\n```\n\nOr rely on SDK defaults which handle this automatically:\n\n```xml\n\u003CAppendTargetFrameworkToOutputPath>true\u003C\u002FAppendTargetFrameworkToOutputPath>\n\u003CAppendTargetFrameworkToIntermediateOutputPath>true\u003C\u002FAppendTargetFrameworkToIntermediateOutputPath>\n```\n\n### Shared output directory across projects (CANNOT be fixed with AppendTargetFramework)\n\n**Problem:** Multiple projects explicitly set the same `BaseOutputPath` or `BaseIntermediateOutputPath`.\n\n```xml\n\u003C!-- Project A - Directory.Build.props -->\n\u003CBaseOutputPath>..\\SharedOutput\\\u003C\u002FBaseOutputPath>\n\u003CBaseIntermediateOutputPath>..\\SharedObj\\\u003C\u002FBaseIntermediateOutputPath>\n\n\u003C!-- Project B - Directory.Build.props -->\n\u003CBaseOutputPath>..\\SharedOutput\\\u003C\u002FBaseOutputPath>\n\u003CBaseIntermediateOutputPath>..\\SharedObj\\\u003C\u002FBaseIntermediateOutputPath>\n```\n\n**IMPORTANT:** Even with `AppendTargetFrameworkToOutputPath=true`, this will still clash! .NET writes certain files directly to the `IntermediateOutputPath` without the TargetFramework suffix, including:\n\n- `project.assets.json` (NuGet restore output)\n- Other NuGet-related files\n\nThis causes errors like `Cannot create a file when that file already exists` during parallel restore.\n\n**Fix:** Each project MUST have a unique `BaseIntermediateOutputPath`. Do not share intermediate output directories across projects:\n\n```xml\n\u003C!-- Project A -->\n\u003CBaseIntermediateOutputPath>..\\obj\\ProjectA\\\u003C\u002FBaseIntermediateOutputPath>\n\n\u003C!-- Project B -->\n\u003CBaseIntermediateOutputPath>..\\obj\\ProjectB\\\u003C\u002FBaseIntermediateOutputPath>\n```\n\nOr simply use the SDK defaults which place `obj` inside each project's directory.\n\n### RuntimeIdentifier builds clashing\n\n**Problem:** Building for multiple RIDs without RID in path.\n\n**Fix:** Ensure RuntimeIdentifier is in the path:\n\n```xml\n\u003CAppendRuntimeIdentifierToOutputPath>true\u003C\u002FAppendRuntimeIdentifierToOutputPath>\n```\n\n### Multiple solutions building the same project\n\n**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.\n\n**How to detect:** Compare `SolutionFileName` and `CurrentSolutionConfigurationContents` across evaluations for the same project. Different values indicate multi-solution builds. For example:\n\n| Property | Eval from Solution A | Eval from Solution B |\n|---|---|---|\n| `SolutionFileName` | `BuildAnalyzers.sln` | `Main.slnx` |\n| `CurrentSolutionConfigurationContents` | 1 project entry | ~49 project entries |\n| `OutputPath` | `bin\\Release\\netstandard2.0\\` | `bin\\Release\\netstandard2.0\\` ← **clash** |\n\n**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`.\n\n**Fix:** Options include:\n1. **Consolidate solutions** - Ensure each project is only built from one solution in a single build\n2. **Use different configurations** - Build solutions with different `Configuration` values that result in different output paths\n3. **Exclude duplicate projects** - Use solution filters or conditional project inclusion to avoid building the same project twice\n\n### Extra global properties creating redundant project instances\n\n**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.\n\n**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:\n\n| Property | Eval A (from Razor.slnx) | Eval B (from Razor.slnx) |\n|---|---|---|\n| `PublishReadyToRun` | *(not set)* | `false` |\n| `OutputPath` | `bin\\Release\\netstandard2.0\\` | `bin\\Release\\netstandard2.0\\` ← **clash** |\n\nThis 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).\n\n**Fix:** Options include:\n1. **Remove the extra global property** - Investigate which parent target\u002Ftask is injecting the property and prevent it from being passed to projects that don't need it\n2. **Use `RemoveGlobalProperties` metadata** - On `ProjectReference` items, use `RemoveGlobalProperties=\"PublishReadyToRun\"` to strip the property before building the referenced project\n3. **Condition the property** - Only set the property on projects that actually use it (e.g., only for executable projects, not class libraries)\n\n### Explicit `\u003CMSBuild>` Build\u002FPublish with extra global properties (self or cross-project)\n\n**Problem:** A target uses the `\u003CMSBuild>` 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):\n\n```xml\n\u003C!-- (a) same project (publish-on-build) -->\n\u003CTarget Name=\"PublishOnBuild\" AfterTargets=\"Build\">\n  \u003CMSBuild Projects=\"$(MSBuildProjectFullPath)\" Targets=\"Publish\" Properties=\"_IsPublishing=true\" \u002F>\n\u003C\u002FTarget>\n\n\u003C!-- (b) project A publishes project B that it consumes -->\n\u003CMSBuild Projects=\"..\\tool\\tool.csproj\" Targets=\"Publish\" Properties=\"_IsPublishing=true\" \u002F>\n```\n\nEither way this forks a distinct instance of the target project (`path` + `{_IsPublishing=true}`) that shares the same `OutputPath`\u002F`IntermediateOutputPath` as the instance the solution\u002Fgraph already builds. Both write the same files — for NativeAOT this includes the `*.sourcelink` intermediate, which produces `SourceLinkWriter` \u002F \"file in use\" failures under parallel builds.\n\n**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`\u002F`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\u002Fprojects tools): the target project itself for (a), or a consumer project that invoked the `\u003CMSBuild>` task for (b).\n\n**Fix:** Depends on where the call lives:\n\n- **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`\u002F`CallTarget`, with a guard against a target cycle when publish is the entry point:\n\n```xml\n\u003CPropertyGroup>\n  \u003C_PublishWasInvokedDirectly Condition=\"'$(_IsPublishing)' == 'true'\">true\u003C\u002F_PublishWasInvokedDirectly>\n  \u003C_IsPublishing>true\u003C\u002F_IsPublishing>\n\u003C\u002FPropertyGroup>\n\u003CTarget Name=\"PublishOnBuild\"\n        AfterTargets=\"Build\"\n        DependsOnTargets=\"Publish\"\n        Condition=\"'$(_PublishWasInvokedDirectly)' != 'true'\" \u002F>\n```\n\n- **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:\n\n```xml\n\u003CItemGroup>\n  \u003CProjectReference Include=\"..\\tool\\tool.csproj\" ReferenceOutputAssembly=\"false\" \u002F>\n\u003C\u002FItemGroup>\n\u003C!-- consumer reads tool's publish dir; it does NOT invoke Publish on tool -->\n```\n\nSee the `msbuild-antipatterns` skill (AP-22) for the authoring-time smell and rationale.\n\n### `SetTargetFramework` re-injecting a single-targeting project's own TFM on a `ProjectReference`\n\n**Problem:** A `ProjectReference` sets `SetTargetFramework=\"TargetFramework=\u003Ctfm>\"` metadata pointing at a **single-targeting** project (one that uses singular `\u003CTargetFramework>`, not `\u003CTargetFrameworks>`), where the injected `\u003Ctfm>` **equals the TFM the project already targets**. `SetTargetFramework` injects `TargetFramework` as a **global property** on the referenced project's build.\n\n```xml\n\u003C!-- BAD: Tool.csproj single-targets net8.0 and we inject that SAME net8.0 -->\n\u003CProjectReference Include=\"..\\Tool\\Tool.csproj\" SetTargetFramework=\"TargetFramework=net8.0\" \u002F>\n```\n\nInjecting the TFM the project already targets is **path-neutral** — the project already resolves to `bin\\\u003Cconfig>\\net8.0\\` and `obj\\\u003Cconfig>\\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\u002Fgraph builds the very same project as `(project, {})`. Both share the same `OutputPath`\u002F`IntermediateOutputPath`, so the project is **built twice** to the same location — a bin\u002Fobj clash under parallel builds.\n\n**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`\u002F`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.\n\n**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.\n\n**Fix:** Remove the redundant `SetTargetFramework` when it just restates the project's own single TFM:\n\n```xml\n\u003C!-- GOOD -->\n\u003CProjectReference Include=\"..\\Tool\\Tool.csproj\" \u002F>\n```\n\n**When `SetTargetFramework` is legitimate (not a clash):**\n\n- **Multi-targeting reference** — the referenced project uses `\u003CTargetFrameworks>` and you need one specific TFM. Each TFM has a distinct output path, so no clash.\n- **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\\\u003Cconfig>\\\u003Cdifferent-tfm>\\`), the instance no longer collides with `(project, {})`. Only the *same-TFM* case is path-neutral and clashing.\n- **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\u002Fsequence the build):\n\n  ```xml\n  \u003CProjectReference Include=\"..\\Tool\\Tool.csproj\"\n                    SkipGetTargetFrameworkProperties=\"true\"\n                    ReferenceOutputAssembly=\"false\" \u002F>\n  ```\n\n  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 \u002F output path. Prevent it by either setting `SetTargetFramework=\"TargetFramework=\u003Ctfm>\"` (pin the TFM) **or** `UndefineProperties=\"TargetFramework\"` (strip the inherited global property so the project builds as it declares) — use one, not both:\n\n  ```xml\n  \u003CProjectReference Include=\"..\\Tool\\Tool.csproj\"\n                    SkipGetTargetFrameworkProperties=\"true\"\n                    UndefineProperties=\"TargetFramework\"\n                    ReferenceOutputAssembly=\"false\" \u002F>\n  ```\n\nSee the `msbuild-antipatterns` skill (AP-23) for the authoring-time smell and rationale.\n\n## Tips\n\n- The SDK default paths include `$(TargetFramework)` — clashes often occur when projects override these defaults; normalize relative paths to absolute before comparing.\n- **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.\n- 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.\n\n### Global Properties to Check When Comparing Evaluations\n\nWhen multiple evaluations share an output path, compare these global properties to understand why:\n\n| Property | Affects OutputPath? | Notes |\n|----------|---------------------|-------|\n| `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...\") |\n| `RuntimeIdentifier` | Yes | Different RIDs should have different paths |\n| `Configuration` | Yes | Debug vs Release |\n| `Platform` | Yes | AnyCPU vs x64 etc. |\n| `SolutionFileName` | No | Identifies which solution built the project — different values indicate multi-solution clash |\n| `SolutionName` | No | Solution name without extension |\n| `SolutionPath` | No | Full path to the solution file |\n| `SolutionDir` | No | Directory containing the solution file |\n| `CurrentSolutionConfigurationContents` | No | XML with project entries — count of entries reveals which solution |\n| `BuildProjectReferences` | No | `false` = P2P query, not a real build - ignore these |\n| `MSBuildRestoreSessionId` | No | Present = restore phase evaluation |\n| `PublishReadyToRun` | No | Publish setting, doesn't change build output path but creates distinct project instances |\n| `_IsPublishing` | No | Publish flag; an `\u003CMSBuild>` Build\u002FPublish call with this set (in this project or another that consumes it) forks a publish instance sharing the build output path (see \"Explicit `\u003CMSBuild>` Build\u002FPublish with extra global properties\") |\n\n## Testing Fixes\n\nAfter 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.\n",{"name":5,"license":15,"description":7},"main","8bdfc29f415696738d845d56aca5d438d0a068de",".agents\u002Fskills\u002Fcheck-bin-obj-clash",315,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-12 02:10:33",{"source":8,"skillName":5,"commands":63,"prompt":73,"zipAvailable":74},[64,67,70],{"tool":65,"command":66},"npx","npx skills add microsoft\u002Ftestfx --skill check-bin-obj-clash",{"tool":68,"command":69},"bunx","bunx skills add microsoft\u002Ftestfx --skill check-bin-obj-clash",{"tool":71,"command":72},"pnpm","pnpm dlx skills add microsoft\u002Ftestfx --skill check-bin-obj-clash","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fcheck-bin-obj-clash\u002FSKILL.md",true,[],[77,103,127,146,165,190],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":48},"01M70GYY0AV0JGMTHE2CN6TNYK","dotnet-breaking-changes","Use before changing .NET\u002FC# code whose callers you do not control: a NuGet library, or a repo with PublicAPI.Shipped\u002FUnshipped.txt, ApiCompat, multiple TargetFrameworks, InternalsVisibleTo, or generated (.g.cs) partials. Green builds miss silent breaks from optional parameters, parameter names, sealing, const values, nullability, and #if. USE FOR: \"without breaking existing callers\"; adding a public method, overload, optional parameter, or interface member to a shipped library; renaming a public method or an internal helper a friend assembly uses; consolidating duplicated logic; changing a signature, nullability, default, or attribute; adding a target framework; RS0016\u002FRS0017 or ApiCompat errors; \"is this PR breaking?\". For a rename, extract, or merge, also invoke csharp-refactoring. DO NOT USE FOR: an executable whose callers all live in one project; renaming a local variable or private member, even in a shipped library; formatting; framework\u002FSDK\u002FNuGet upgrades (use dotnet-upgrade).","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fdotnet-breaking-changes\u002FSKILL.md",[],[84,85,86,87,43,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102],"dotnet","dotnet breaking changes","changes","green","default","local","errors","interface","generated","upgrade","invoke","you","code","refactoring","merge","rename","library","live","assembly",{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":110,"publishedAt":48},"01M699HHE9DTZWAMPB1ZR7ZKSW","testfx-test-value-evidence","Apply the vendored test-value-evidence skill with TestFx toolchain, assertion, parallel-safety, packed-consumer, and review conventions. Use when implementing or reviewing behavior-changing TestFx PRs or commits, including source-only changes.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftestfx-test-value-evidence\u002FSKILL.md",[109],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[111,112,113,114,115,116,36,117,118,119,120,121,31,41,122,123,86,124,125,126],"test","testfx test value evidence","test value evidence","evidence","value","review","toolchain","commits","implementing","prs","only","apply","with","behavior","Safety","conventions",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"publishedAt":48},"01M699HEYWH1B9XGNBFY8J2FZS","testfx-parallel-safety-preflight","Check concurrency and isolation before implementing or refactoring TestFx tests, lifecycle code, helpers, shared-state declarations, or production paths those tests exercise. Use before narrowing DoNotParallelize or ResourceLock, changing parallelization settings, or introducing asynchronous workers; repeat against the final diff.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftestfx-parallel-safety-preflight\u002FSKILL.md",[],[134,125,135,36,46,136,119,137,96,138,97,38,139,140,141,142,143,144,31,145],"testfx parallel safety preflight","preflight","asynchronous","exercise","concurrency","isolation","helpers","diff","parallelization","lifecycle","tests","workers",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":48},"01M699HC61ZV9GJ2C8JV03951G","testfx-localization-validation","Validate generated TestFx localization catalogs, resource IDs, placeholders and locked tokens. Use for RESX\u002FXLF changes, OneLoc PRs, localization build failures, duplicate targets or units, and orphaned translation entries.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftestfx-localization-validation\u002FSKILL.md",[],[153,154,155,156,157,158,34,159,160,120,92,31,161,162,86,163,164],"testfx localization validation","validation","localization","validate","translation","ids","tokens","entries","units","duplicate","targets","build",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":169,"categories":170,"keywords":172,"publishedAt":48},"01M699H9J2NWQXE4BDT6R0FH7S","testfx-acceptance-validation","Validate TestFx shipping paths and capable CI execution using packed consumers, package\u002Fcache provenance, exact exits and artifacts, and selected-versus-executed test evidence. Use for acceptance regressions, package\u002FMSBuild\u002Flauncher\u002Fprotocol changes, or skipped-only CI results; not for unrelated unit-only or documentation changes.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftestfx-acceptance-validation\u002FSKILL.md",[171],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[173,174,154,111,175,114,176,177,178,121,179,31,180,181,182,183,184,185,186,187,188,189,38,34],"testfx acceptance validation","acceptance","msbuild","launcher","ci","execution","package","cache","artifacts","provenance","documentation","unrelated","shipping","results","protocol","unit","ci results",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":194,"categories":195,"keywords":196,"publishedAt":48},"01M699H70BB999BT4F627T1PHE","session-delivery-hygiene","Gate local-session scope, persistent delivery, live PR state, integration provenance, and owned cleanup. Use before implementing guidance changes, changing or pushing PR work, diagnosing package\u002Foutput mismatches, or handing off implementation.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftestfx\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsession-delivery-hygiene\u002FSKILL.md",[],[197,198,199,200,201,119,89,202,39,101,203,179,31,182,204,205,86,206,207,208],"session delivery hygiene","delivery","session","hygiene","scope","cleanup","pr","output","state","integration","guidance","gate"]