v0.1.0 to v0.1.0

6 added, 4 removed. Audit A to A.

---
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`.
For ordinary API diffs with one Library on each side, the endpoints must have
the same assembly name, culture, and public-key token; assembly versions may
differ. The CLI uses the portable Library comparison contract intended for
website Compare. Type-definition or member changes without a compatibility
assessment remain visible as **Other API Changes** (`unclassified` in
`-S Changes --json`/`--jsonl`/`--tsv`). Do not treat them as safe or breaking;
`--breaking` and `--additive` select only their assessed classifications.
An incomplete or rejected comparison returns nonzero and reports **not
compared**. Missing generic-constraint dependencies retain their inspection
failure evidence. Invalid managed-image inputs report the admission error on
stderr. Do not interpret these outcomes as “no API changes.” Multi-Library
packages, `-m` filtering, Analysis Diff, Implementation Diff, Finding
Transitions, and mixed-section requests retain their existing routes.
For a complete shared single-Library API result, use unprojected `--json`.
It emits `LibraryApiDiffOutcome`: `outcome` is `available`, `unavailable`, or
`rejected`, with the complete Document or typed non-success endpoint evidence.
This replaces the former unprojected `{changes: ...}` view. Explicitly
filtered or sectioned JSON still uses the presentation schema.
Use `--envelope` for the same Content plus Share and diagnostics, with
`schema_version: 1` and `result_kind: "library-api-diff"`. `--all` is admitted;
Type/classification filters, sections, explicit verbosity, row/line windows,
and other Diff modes are not. Add `--compact` to either JSON form for compact
whitespace; it is rejected with projected or other Diff operations. Share is
non-projectable for the ordered comparison endpoints.
This does not add Evidence capture or change the current Browser projection.
## Where did this API coordinate go?
Use subject-owned `--match` when the question is correspondence for one Type or
Member rather than all API changes:
```bash
dnx dotnet-inspect -y -- type System.Text.Json.Schema.JsonSchemaExporter \
--package System.Text.Json@9.0.0..8.0.6 --match
dnx dotnet-inspect -y -- member System.Text.Json.JsonSerializer Deserialize:1 \
--package System.Text.Json@9.0.0..10.0.0 --match
```
The endpoints are two literal versions and remain in caller order. A Member
selector is resolved at the source only; use a unique name, `Name:N`,
`Name~digest`, or `--index N`. The destination coordinate comes from API
correspondence, so do not resolve the same ordinal independently there.
This operation matches declarations, not accessor bodies. A selector such as
`Foo:1` or `Foo~digest:1` is refused when the ordinal selects an accessor of a
singleton Property/Event; omit the accessor ordinal to match the declaration.
An ordinal selecting among overloaded indexer declarations remains valid.
`--tfm` selects one API surface, optional `--library` narrows only the source
Library, and `--all` widens only source selection to the existing IncludeAll
API scope. Destination declaration matching remains strict and independent of
ordinary accessibility changes. Use `--json` for complete Content or
`--envelope` for Content, Share, and diagnostics. Do not combine this mode with
History, `--at`, row projections, projection filters, sections,
body/source/Analysis requests, or non-package sources. Root `match` is
unrelated implementation-clone comparison.
Like whole-Library API Diff, `type`/`member --match` currently reports
`share.kind: "nonProjectable"` because the portable scenario does not represent
ordered correspondence endpoints. The envelope is still useful for the
complete typed match outcome and diagnostics. To hand the user one endpoint,
run a separate exact Package-backed `member ... --share url`; that URL opens
the public API Overview and does not preserve the correspondence operation.
## 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 `-S @Diff` to compose the API `Changes`, `Analysis Diff`, and
`Implementation Diff` views. `Finding Transitions` remains exact-name-only
because its focused endpoint-confirmation semantics do not compose with them.
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 + PDB Source)
- `-S "Implementation Diff"` selects Research-composed body evidence instead of
- the default API compatibility view. Rows identify the member, producer (`C#`,
- `IL`, or `PDB Source`), change kind, and producer-owned evidence. `C#` is
+ `--implementation` is the conventional shortcut for exact
+ `-S "Implementation Diff"` selection. It selects Research-composed body
+ evidence instead of the default API compatibility view. Rows identify the
+ member, producer (`C#`, `IL`, or `PDB Source`), change kind, and producer-owned
+ evidence. `C#` is
decompiled text; `PDB Source` is Portable-PDB-selected, checksum-verified text
acquired locally or through SourceLink. The lanes are peers: PDB-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" --pdb-source --repo /path/to/Foo \
+ --implementation --pdb-source --repo /path/to/Foo \
-t MyType -m HotPath
```
`--repo` requires a fully qualified clone path. For
`raw.githubusercontent.com` SourceLink URLs, it reads the committed blob at the
SourceLink commit and verifies it against the PDB checksum before fetching the
source body remotely. Package or PDB acquisition may still use the network;
other SourceLink hosts do not use the local-repository path. Treat these rows
as implementation evidence, not semantic-equivalence proof.
For one explicitly selected method and one library per endpoint,
`--pdb-source` compares authored source even when C# and IL are unchanged.
For example, changing `1 + 2` to `3` can change Source without changing either
compiled lane. The selected Source lane also reports unchanged or unavailable
evidence, retaining acquisition failures rather than treating missing text as
a deletion. Broader selections still enrich the locally changed members.
## What can be configured? (feature switches)
`-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 source-scoped. Use `package Foo --versions -n 1` for one
newest listed version row, or `package Foo@latest --versions` when the answer
must be freshly discovered across every eligible configured source without
legacy candidate cache reuse. Use `package Foo --version 1.2.3` to verify one
exact version and `Foo --versions` (add `-n N` for N rows or `--preview` for
prerelease) to list published versions. Unlisted versions are hidden unless
`--include-unlisted` is explicit. `--versions-with-feed` retains each
version/feed pair when source identity matters. Source declaration order is not
precedence; load the `private-feeds` skill for source and credential workflows.
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 -- diff --history --package Foo@1.0.0..2.0.0 \
--type TargetType --members --at first --at last
dnx dotnet-inspect -y -- diff --history --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.
Online API/history ranges support configured folder and HTTP feeds. Discovery
must be complete, and each probe can acquire only from a source that reported
its coordinate. These vectors are listed-only; an `--include-unlisted`
metadata listing can have different ordinals. Use an exact pin to inspect an
unlisted coordinate. Local payload caches retain configured authority; HTTP
payloads use temporary storage and are downloaded again on a later invocation.
Diff History renders `Evaluations` and `Transitions` over the same vector. Omit
`--at` for full-population evaluation, repeat it for explicit checkpoints, or
use `--max-probes` for adaptive bisection. Add `--sample-percent P` for a
deterministic population-relative survey, optionally capped by `--max-probes`.
Use `--major-versions` for one representative per major: API findings choose
the first stable version, with the latest prerelease fallback for preview-only
majors, while Analysis findings choose the latest admitted version per major.
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` history to one method body.
Gap-spanning transitions are evidence across the selected probes, not claims
about the exact introduction or removal version.
Online recommendations retain source/configuration, TFM, prerelease, and
visibility options so the next probe can run from a different working directory.
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.