---
name: dotnet-inspect-compatibility
version: 0.1.0
description: Decide whether a change or upgrade is safe — API-surface diffs, behavioral diffs (allocations, exceptions), feature switches, and version resolution.
---

# dotnet-inspect: compatibility and change analysis

Use this skill to decide whether a change is safe to adopt: what changed between
two versions and what surface a library exposes. The scenario crosses commands —
`diff` for change, `library`/`package` for the surface a single version exposes.

```bash
dnx dotnet-inspect -y -- <command>
```

## Did the API surface change?

`diff` compares a version range from a package, a platform (in-box) library, or
two local builds. Pick the lens for the question you are answering:

```bash
dnx dotnet-inspect -y -- diff --package System.Text.Json@9.0.0..10.0.0 --breaking
dnx dotnet-inspect -y -- diff --platform System.Runtime@9.0.0..10.0.0 --additive
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll --changed
```

`--breaking` for migration work, `--additive` for release notes, `--changed`
for in-place member changes, `--name-only` for a quick list. Narrow with
`-t TypeName`; widen with `--all`.

## Did runtime behavior change? (allocations, exceptions)

`-S "Analysis Diff"` compares body-level signal *deltas* between the two
versions, not just the API shape. Rows are `Member | Signal | Old | New |
Delta`, where `Signal` covers `allocations`, `copies`, `reflection`, `throws`,
`catches`, `finallys`, `unsafe`, `constructed-exceptions`, and `optimization`
shapes. This is how you catch an allocation regression or a change in exception
coverage across versions. (For what these signals mean on a single version, see
the `performance` and `correctness` skills.)

```bash
dnx dotnet-inspect -y -- diff --package Foo@1.0.0..2.0.0 -S "Analysis Diff"
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll -S "Analysis Diff" --changed
```

Use `Analysis Diff` for aggregate regression triage. To confirm whether one
allocation occurrence was introduced at a caller-selected boundary, resolve one
method and request the native Analysis Finding pairs:

```bash
dnx dotnet-inspect -y -- diff --package Foo@1.4.0..1.5.0 \
  -t Foo.Parser -m Parse \
  --finding analysis.allocation
```

`PairFinding.Added` with `Old=absent` and `New=present` confirms allocation
onset. `Present`, `Removed`, and `Changed` remain distinct; do not infer onset
from an aggregate allocation-count delta.

For a direct-call boundary in one caller method, select the call-site producer:

```bash
dnx dotnet-inspect -y -- diff --package Foo@1.4.0..1.5.0 \
  -t Foo.Parser -m Parse \
  --finding analysis.call-site
```

Rows identify the callees. `PairFinding.Added` confirms a new direct-call
occurrence; `Changed` reports retained-call facet changes such as moving into a
loop.

For a definite unsafe-operation boundary in one method, select the unsafety
producer:

```bash
dnx dotnet-inspect -y -- diff --package Foo@1.4.0..1.5.0 \
  -t Foo.Parser -m Parse \
  --finding analysis.unsafety
```

Rows identify unsafe operation kinds and details. `PairFinding.Added` confirms
introduction; `Present` and `Removed` distinguish persistence from
disappearance without treating endpoint-local IL offsets as identity.

## Did the implementation change? (decompiled C# + IL + authored Source)

`-S "Implementation Diff"` selects Research-composed body evidence instead of
the default API compatibility view. Rows identify the member, producer (`C#`,
`IL`, or `Source`), change kind, and producer-owned evidence. `C#` is
decompiled text; `Source` is checksum-verified authored SourceLink text. The
lanes are peers: Source absence or failure stays visible and never replaces the
C# lane. Narrow with `-t` and `-m`; use `--table`, `--tsv`, or `--jsonl` for
columnar output.

```bash
dnx dotnet-inspect -y -- diff --library old/Foo.dll..new/Foo.dll \
  -S "Implementation Diff" --authored-source -t MyType -m HotPath
```

Treat these rows as implementation evidence, not semantic-equivalence proof.

## What can be configured? (feature switches)

`-S Switches` (alias `-S @Switches`) on `library` or `package --library` reports
the behavior and trim/AOT knobs: `[FeatureSwitchDefinition]`s, runtime host
configuration options, and `AppContext` switches.

```bash
dnx dotnet-inspect -y -- library System.Text.Json -S Switches
```

## Which versions to compare

Version resolution is cache-first (local cache in milliseconds; nuget.org
~1–4s). Use `Foo --version` for the cached version a bare inspection will use,
`Foo --latest-version` for the newest on nuget.org, and `Foo --versions [N]`
(add `--preview`) to list published versions. Pin with `@`: `Foo@9.0.0`,
`Foo@latest`.

For caller-driven onset or bisect work, resolve an inclusive addressable vector,
then probe only the cells you choose:

```bash
dnx dotnet-inspect -y -- package Foo@1.0.0..2.0.0 --versions
dnx dotnet-inspect -y -- type TargetType --package Foo@1.0.0..2.0.0 --at '#5'
dnx dotnet-inspect -y -- member TargetType TargetMember --package Foo@1.0.0..2.0.0 --at 1.6.0
dnx dotnet-inspect -y -- timeline --package Foo@1.0.0..2.0.0 \
  --type TargetType --members --at first --at last
dnx dotnet-inspect -y -- timeline --package Foo@1.0.0..2.0.0 \
  --type TargetType --member TargetMember \
  --finding analysis.unsafety --at first --at last
```

`--at` accepts an exact version, one-based `#N`, `first`, or `last`. Vector
resolution does not download every package; only the selected probe is
acquired. The agent owns the search policy and bound. For recurrence-safe
current onset, walk backward from the bad version until the first successful
absence; use binary search only for a predicate known to be monotonic.

`timeline` renders `Evaluations` and `Transitions` over the same vector. Omit
`--at` for a zero-payload address view and midpoint recommendation, repeat
`--at` for sparse probes, or pass `--at all` for explicit dense traversal.
Choose the type-focused census with `--type-presence`, `--members`, or
`--attributes` (aliases for `api.type`, `api.member`, and `api.attribute`).
Add `--member` to `api.member` for one exact member identity track. The same
member selector scopes `analysis.allocation`, `analysis.call-site`, and
`analysis.unsafety` timelines to one method body.
Gap-spanning transitions are evidence across the selected probes, not claims
about the exact introduction or removal version.

The range and point probes identify a candidate boundary. Confirm the adjacent
pair with Metadata's real Finding comparison rather than inferring introduction
from probe text:

```bash
dnx dotnet-inspect -y -- diff \
  --package System.Text.Json@8.0.6..9.0.0 \
  -t System.Text.Json.Schema.JsonSchemaExporter \
  -S "Finding Transitions"
```

An introduction boundary is a row with `PairFinding.Added`, `Old=absent`, and
`New=present`. `PairFinding.Present` means the target exists at both endpoints;
for a type target, no row means it exists at neither. Use `-m Type.Member:1` for
an API member boundary. Use `--finding analysis.allocation`,
`--finding analysis.call-site`, or `--finding analysis.unsafety` with exactly
one method target for the corresponding Analysis boundary.
Use `--finding csharp.line` or `--finding il.op` with exactly one method target
to inspect native implementation-census transitions. Those lenses preserve
complete, absent, and failed outcomes, including added or removed methods.
