diff --git a/.releaserc.json b/.releaserc.json index 5544cee6..ea5f06dc 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -5,7 +5,7 @@ ["@semantic-release/commit-analyzer", { "preset": "conventionalcommits", "releaseRules": [ - { "breaking": true, "release": "minor" }, + { "breaking": true, "release": "major" }, { "type": "feat", "release": "minor" }, { "type": "fix", "release": "patch" }, { "type": "perf", "release": "patch" }, diff --git a/CLAUDE.md b/CLAUDE.md index 2e84ad6f..e0f5a616 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -239,10 +239,12 @@ say so. Twice in one wave that phrasing turned an obvious fix into a wait. ## Versioning -Until the `v1.3.0` tag, `docs/decisions/0001-versioning-and-api-stability.md` governs: breaking -changes are allowed, they map to a **minor** bump, and no `[Obsolete]` shim is introduced to dodge -one. `eng/verify-release-config.mjs` enforces both ends of that and fails the build if the rule -and the changelog disagree. +1.3.0 is out (`v1.3.0`), so the window that `docs/decisions/0001-versioning-and-api-stability.md` +describes is closed and SemVer holds. A breaking change needs the `!` and a `BREAKING CHANGE:` footer in +the commit message and publishes a **major** version: `.releaserc.json` maps `breaking` to `major`, and +`eng/verify-release-config.mjs` fails the build if it maps to anything else. A deprecation is an +`[Obsolete]` member that a later major removes. The decision record stays as the account of how 1.3.0 +came about. ## Upstream diff --git a/GitVersion.yml b/GitVersion.yml index 952c0981..28ab2a60 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -72,12 +72,12 @@ branches: # artifact list reads exactly like one. With the label it is `1.2.4-ci.12` and says so, which # is the whole of what this needs to fix. # - # Increment stays Patch. Raising it to Minor while the work heads for 1.3.0 would name CI - # artifacts after the version they are heading for -- but `increment` is unconditional, so it - # would go on producing 1.4.0-ci.N after 1.3.0 ships instead of 1.3.1-ci.N, and nothing would - # restore it. One temporary override with a machine-enforced expiry (breaking -> minor, in - # .releaserc.json) is a debt worth carrying; a second one, for nothing but the cosmetics of an - # artifact name, is not. + # Increment stays Patch. Raising it to Minor while the work headed for 1.3.0 would have named CI + # artifacts after the version they were heading for -- but `increment` is unconditional, so it + # would have gone on producing 1.4.0-ci.N after 1.3.0 shipped instead of 1.3.1-ci.N, and nothing + # would restore it. The one temporary override this repository carried, with a machine-enforced + # expiry (breaking -> minor, in .releaserc.json), was worth its cost; a second one, for nothing + # but the cosmetics of an artifact name, was not. label: ci increment: Patch pull-request: diff --git a/README.md b/README.md index e1f6b393..5275acf1 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,11 @@ Everything targets `netstandard2.0` and `net10.0`. ## Status -The 1.0.0 – 1.2.3 releases are **withdrawn from nuget.org**: they were published as stable before the API -had been reviewed against the specifications. **1.3.0 will be the first release whose API is -stable**, and the surface can still change until it is tagged — see -[Versioning](docs/decisions/0001-versioning-and-api-stability.md) for what that window is for. - -Which means there is **nothing to install from nuget.org until 1.3.0 ships**: the `dotnet add -package` lines below have no listed version to resolve, and a withdrawn release comes back only -on an exact version pin. Build from source in the meantime. +**1.3.0 is the first stable release.** From 1.3.0 on the public API follows SemVer: a breaking change costs a +major version, and a deprecation is an `[Obsolete]` member that a later major removes. The 1.0.0 – 1.2.3 +releases were published as stable before the API had been reviewed against the specifications; they are +unlisted and deprecated on nuget.org and should not be used. See +[Versioning](docs/decisions/0001-versioning-and-api-stability.md) for how that came about. ## Install diff --git a/docs/architecture/arc42-CanKit.Pro.md b/docs/architecture/arc42-CanKit.Pro.md index 594cf4c9..874caa23 100644 --- a/docs/architecture/arc42-CanKit.Pro.md +++ b/docs/architecture/arc42-CanKit.Pro.md @@ -151,7 +151,7 @@ Zero-Copy) erhöhen den Aufwand für Q4 und für einen sicheren **Frame-Ownershi ## 2.2 Organisatorische Randbedingungen - **OSS-Paket** (MIT, `LICENSE`), als NuGet-Pakete gemeinsam versioniert und veröffentlicht. Die - Releases 1.0.0 – 1.2.3 sind zurückgezogen; 1.3.0 wird der erste Release mit stabiler API + Releases 1.0.0 – 1.2.3 sind zurückgezogen; 1.3.0 ist der erste Release mit stabiler API (README § Status, `docs/decisions/0001-versioning-and-api-stability.md`). - **Eine CI über die gesamte Solution** (`.github/workflows/ci.yml`; Trigger: Push auf `main`, Pull Requests, `merge_group`). Die adapterweisen Pfadfilter und Solution-Filter der Erstfassung diff --git a/docs/decisions/0001-versioning-and-api-stability.md b/docs/decisions/0001-versioning-and-api-stability.md index 021ff2b5..6cb4a6fd 100644 --- a/docs/decisions/0001-versioning-and-api-stability.md +++ b/docs/decisions/0001-versioning-and-api-stability.md @@ -1,7 +1,7 @@ # Versioning: 1.3.0 is the first stable release -**Status:** accepted, 2026-09-12. Resolves -[#61](https://github.com/dborgards/CanKit.Pro/issues/61). +**Status:** accepted, 2026-09-12; carried out with the release of 1.3.0 on 2026-09-30, see +[Outcome](#outcome) at the end. Resolves [#61](https://github.com/dborgards/CanKit.Pro/issues/61). ## Context @@ -183,3 +183,36 @@ versions. Normal SemVer. A breaking change costs a major version; a deprecation is an `[Obsolete]` member that a later major removes. The API approval tests are what make an accidental break visible in the pull request that causes it. + +## Outcome + +Written on 2026-09-30, after the release; the text above is left as decided. + +1.3.0 was released on 2026-09-30: tag `v1.3.0`, all nine packages on nuget.org, and the changelog +commit `chore(release): 1.3.0` on `main`. + +Against the checklist: + +1. Every `type: bug` issue was closed. The two issues open at the time, [#246](https://github.com/dborgards/CanKit.Pro/issues/246) + (documentation) and [#240](https://github.com/dborgards/CanKit.Pro/issues/240) (a test that failed + once on CI), are not of that type. +2. [#52](https://github.com/dborgards/CanKit.Pro/issues/52) was closed with the normative negative tests. +3. [#23](https://github.com/dborgards/CanKit.Pro/issues/23), [#37](https://github.com/dborgards/CanKit.Pro/issues/37), + [#44](https://github.com/dborgards/CanKit.Pro/issues/44) and [#82](https://github.com/dborgards/CanKit.Pro/issues/82) + had landed. +4. The approval baselines were gone through for shapes that are hard to change later. That review was not + line by line, and it led to three further breaking changes before the tag: `SendConfirmed` became + `SendConfirmedAsync` ([#238](https://github.com/dborgards/CanKit.Pro/pull/238)), and `IProtocolActor.PostAsync` + ([#242](https://github.com/dborgards/CanKit.Pro/pull/242)) and `IIsoTpChannel.SettleAsync` + ([#244](https://github.com/dborgards/CanKit.Pro/pull/244)) gained a `CancellationToken`. + The maintainer took the surface as it then stood over as final by starting the release. +5. Each package README states what is validated and what is not + ([#245](https://github.com/dborgards/CanKit.Pro/pull/245)). + +The pipeline dry run described above failed on its first attempt: the version-resolution step ran +`git push --dry-run` against GitHub in a job that deliberately holds no credentials +([#243](https://github.com/dborgards/CanKit.Pro/pull/243)). It passed after that fix, and 1.3.0 was cut from +the commit it had passed on. + +The `breaking -> minor` override in `.releaserc.json` was reverted to `major` in the change that adds this +section, together with the texts that described the window as open. diff --git a/docs/index.md b/docs/index.md index e9cfe408..057fdc81 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,12 +34,6 @@ designed once instead of improvised in every stack. [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/dborgards/CanKit.Pro/blob/main/LICENSE) -!!! warning "Nothing to install from nuget.org right now" - - 1.0.0 – 1.2.3 are withdrawn, and 1.3.0 is not out yet, so the version badge above reads from - a feed with no listed release and `dotnet add package` has nothing to resolve. Build from - source until 1.3.0 ships. See [Versioning](decisions/0001-versioning-and-api-stability.md). -
diff --git a/docs/packages/index.md b/docs/packages/index.md index 254c0239..d2f9e83f 100644 --- a/docs/packages/index.md +++ b/docs/packages/index.md @@ -8,20 +8,13 @@ description: The nine CanKit.Pro packages, what layer each one lives on, and wha Nine packages, one version number, released together to nuget.org. Take only the layers you need: an ISO-TP application pulls in five of them, a plain demultiplexer one. -!!! warning "1.0.0 – 1.2.3 are withdrawn" +!!! note "1.0.0 – 1.2.3 are withdrawn" These six versions were published as stable before the API had been reviewed against the - specifications, and are unlisted and deprecated on nuget.org. **1.3.0 will be the first - release whose API is stable**; until it is tagged, the public surface can still change. See + specifications, and are unlisted and deprecated on nuget.org. **1.3.0 is the first release + whose API is stable**; use it or later. See [Versioning](../decisions/0001-versioning-and-api-stability.md). - **So there is nothing to install from nuget.org right now.** The `dotnet add package` lines - below have no listed version to resolve until 1.3.0 ships; a withdrawn release comes back - only on an exact version pin, which is not recommended. Build from source in the meantime. - - The version badges in the tables below read from the nuget.org feed, so during this window - they show a withdrawn version or nothing at all. They become meaningful again with 1.3.0. - Everything targets `netstandard2.0` and `net10.0`, so .NET Framework 4.6.2+, .NET 8 and .NET 10 all work. Every package depends on `CanKit.Abstractions` where it touches a bus and on nothing vendor-specific anywhere. diff --git a/docs/release-process.md b/docs/release-process.md index 9a48c73e..025905ef 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -32,13 +32,13 @@ Conventional Commits since the last tag: a `fix` bumps the patch, a `feat` the m `BREAKING CHANGE:` footer the major. It then writes the changelog, creates the tag, publishes the GitHub Release and pushes the packages. It only runs on `main`. -!!! note "Until 1.3.0, a breaking change bumps the minor" +!!! note "Since 1.3.0, a breaking change bumps the major" - `.releaserc.json` currently maps `breaking` to a **minor** release, so that the API - corrections on the way to 1.3.0 cannot publish 2.0.0 by accident. This is temporary and is - on the release checklist in - [Versioning](decisions/0001-versioning-and-api-stability.md); - `eng/verify-release-config.mjs` fails the build if the override outlives 1.3.0. + `.releaserc.json` maps `breaking` to **major** again. Until 1.3.0 it mapped to minor, so that the API + corrections before that release could not publish 2.0.0 by accident; how that came about is in + [Versioning](decisions/0001-versioning-and-api-stability.md). + `eng/verify-release-config.mjs` fails the build if the mapping is anything but major now that + 1.3.0 is in the changelog. **GitVersion** answers *"what version is this commit?"* — for builds that are not releases. A pull-request build or a CI artifact from `main` between releases gets a real, ordered SemVer @@ -131,7 +131,7 @@ Each plugin runs in the order it appears in `.releaserc.json`, within each lifec ``` analyze → nothing to release? stop here -verifyRelease → refuse a version below 1.3.0 while the ADR window is open (exec) +verifyRelease → re-check the release configuration for the version about to go out (exec) prepare → CHANGELOG.md regenerated (@semantic-release/changelog) → verify the nine packages `verify` packed (@semantic-release/exec, prepareCmd) → changelog committed and PUSHED to main (@semantic-release/git) @@ -289,17 +289,14 @@ From the Actions tab: **Release → Run workflow**, leaving *dry run* checked. I version, builds, tests and packs, and prints the release notes it would write — without tagging, publishing, or requesting a NuGet credential. -!!! warning "A dry run cannot succeed before 1.3.0" +!!! note "A dry run has something to say only when a release is pending" - The `verify` job refuses any version that is not 1.3.0 while the pre-1.3.0 window is open, and - the commit analyser computes a patch version until a `feat` commit lands. So a dry run today - stops at the version gate, having proved only that version resolution works. - - This is the gate doing its job, not a fault to route around: it refuses to release before the - checklist in [Versioning](decisions/0001-versioning-and-api-stability.md) is done, and a dry - run goes through the same gate as a real one on purpose. The first dry run that exercises the - whole path is the one taken once the version reaches 1.3.0, and 1.3.0 should not be cut until - that has been green. + The version is resolved from the commits since the last tag. If none of them releases (`docs:`, + `test:`, `chore:`, `ci:`, `refactor:`, `style:`), a dry run resolves no version and reports that there + is nothing to release. Build and test still run, but the Pack and Upload steps are skipped, because + they need a version: such a dry run does not exercise package creation. It resolves a version once a + commit of a releasing type has landed: `feat`, `fix`, `perf`, `revert`, `build(deps)`, or any breaking + commit. Locally, the same analysis without a token, and without the workflow's gates: diff --git a/src/CanKit.Pro.Actor/README.md b/src/CanKit.Pro.Actor/README.md index 60254704..98ced2d7 100644 --- a/src/CanKit.Pro.Actor/README.md +++ b/src/CanKit.Pro.Actor/README.md @@ -5,11 +5,10 @@ Generic protocol-instance actor/scheduler for [CanKit](https://github.com/pkuyo/ layer (ISO-TP, J1939, CANopen, ...) can build on instead of hand-rolling locks, unsynchronized `List`s, and busy-loop schedulers. -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**; until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The public surface -can still change until then. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See +[Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.Addressing/README.md b/src/CanKit.Pro.Addressing/README.md index 1169bad7..3e96ac6b 100644 --- a/src/CanKit.Pro.Addressing/README.md +++ b/src/CanKit.Pro.Addressing/README.md @@ -6,11 +6,10 @@ PDU-Format/Source-Address composition and decomposition, J1939 NAME field access classification helpers, as pure, dependency-free helper functions — no dependency on any other CanKit package. -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**; until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The public surface -can still change until then. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See +[Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.CANopen/README.md b/src/CanKit.Pro.CANopen/README.md index 7456f1c4..ab7dd668 100644 --- a/src/CanKit.Pro.CANopen/README.md +++ b/src/CanKit.Pro.CANopen/README.md @@ -1,10 +1,8 @@ # CanKit.Pro.CANopen -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**. Until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The -public surface can still change until then. See +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.IsoTp/README.md b/src/CanKit.Pro.IsoTp/README.md index beb3c3ca..2c819c80 100644 --- a/src/CanKit.Pro.IsoTp/README.md +++ b/src/CanKit.Pro.IsoTp/README.md @@ -11,11 +11,9 @@ ISO 15765-2 (ISO-TP) implementation for [CanKit](https://github.com/pkuyo/CanKit Overflow) and enforces N_As/N_Bs/N_Cr timers, reassembles inbound PDUs (SN-checked), and delivers them via `ReceiveAsync` / `ReceiveAllAsync` / `DatagramReceived`. -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**. Until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The -public surface can still change until then. See +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). CAN-FD long-payload cases still get the least coverage of the two halves. diff --git a/src/CanKit.Pro.J1939/README.md b/src/CanKit.Pro.J1939/README.md index e11ac6fe..f8010054 100644 --- a/src/CanKit.Pro.J1939/README.md +++ b/src/CanKit.Pro.J1939/README.md @@ -134,11 +134,9 @@ catalog decodes signed parameters too. ## Status -The 1.0.0 – 1.2.3 releases are **withdrawn from nuget.org** — they were published as stable before the API -had been reviewed. **1.3.0 will be the first release whose API is stable**. Until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The -public surface can still change until then. See +**1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.J1939Tp/README.md b/src/CanKit.Pro.J1939Tp/README.md index db1070b5..1a44f968 100644 --- a/src/CanKit.Pro.J1939Tp/README.md +++ b/src/CanKit.Pro.J1939Tp/README.md @@ -2,11 +2,10 @@ SAE J1939-21 Transport Protocol (TP) for CanKit.Pro. Implements both flavors of the J1939-21 §5.10 transport service: -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**; until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The public surface -can still change until then. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See +[Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.RawCan/README.md b/src/CanKit.Pro.RawCan/README.md index a7958ef8..9e7bda76 100644 --- a/src/CanKit.Pro.RawCan/README.md +++ b/src/CanKit.Pro.RawCan/README.md @@ -4,11 +4,10 @@ Raw-CAN service layer for [CanKit](https://github.com/pkuyo/CanKit): multi-proto demultiplexing / subscriptions (arc42 §5.3, ADR-5; SRS FR-RAW-010..015) and a TX-confirm abstraction (arc42 §6.3, ADR-7; SRS FR-RAW-030..034). -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**; until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The public surface -can still change until then. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See +[Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.Reliability/README.md b/src/CanKit.Pro.Reliability/README.md index af5efa59..c02cda25 100644 --- a/src/CanKit.Pro.Reliability/README.md +++ b/src/CanKit.Pro.Reliability/README.md @@ -6,11 +6,10 @@ checked and fired, and a **bus-state monitor** that pushes `ICanBus.BusState` tr protocol instance — both composed on top of `CanKit.Pro.Actor`'s single-mailbox loop, so there are no free-running timers, no busy loops, and no second background-exception channel. -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**; until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The public surface -can still change until then. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See +[Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not diff --git a/src/CanKit.Pro.Uds/README.md b/src/CanKit.Pro.Uds/README.md index b3415442..4b387f14 100644 --- a/src/CanKit.Pro.Uds/README.md +++ b/src/CanKit.Pro.Uds/README.md @@ -5,17 +5,14 @@ directly on top of `CanKit.Pro.IsoTp`'s `IIsoTpChannel`, so anything that speaks (virtual loopback, PCAN, SocketCAN, Vector, Kvaser, ZLG, ControlCAN, ...) can be driven with the same client. -Status: 1.0.0 – 1.2.3 are **withdrawn from nuget.org** — they were published as stable before -the API had been reviewed. **1.3.0 will be the first release whose API is stable**. Until it is -tagged there is no listed version to install, so the `dotnet add package` line below resolves -nothing and the withdrawn releases come back only on an exact version pin. The -public surface can still change until then — `SendRawAsync`, the timing options and the -NRC-mapping types most of all. See +Status: **1.3.0 is the first stable release**: from 1.3.0 on the public API follows SemVer, so a breaking +change costs a major version. 1.0.0 – 1.2.3 were published as stable before the API had been reviewed +against the specifications; they are unlisted and deprecated on nuget.org and should not be used. See [Versioning](https://github.com/dborgards/CanKit.Pro/blob/main/docs/decisions/0001-versioning-and-api-stability.md). ## What is validated, and what is not -**Validated:** Each service listed under *Service coverage* (some of them thinly), negative-response handling and the timing options, by the test suite in `tests/CanKit.Pro.Tests`, against `SimulatedUdsEcu` — a scripted ECU simulation in this repository whose responses each test defines — over `CanKit.Adapter.Virtual`. +**Validated:** Each service listed under *Service coverage* (some of them thinly), negative-response handling and the timing options, by the test suite in `tests/CanKit.Pro.Tests`, against `SimulatedUdsEcu` — a scripted ECU simulation in this repository whose responses each test defines — over `CanKit.Adapter.Virtual`. The thinnest coverage is the mapping of negative response codes onto `UdsNegativeResponseCode`: only a few codes are asserted by name. `SendRawAsync` and the timing options are exercised heavily, but likewise only against the simulation. **Not validated:** Any real ECU, whose timing, negative-response usage and deviations from the standard the simulation does not reproduce, and conformance as a tester would judge it. Nothing in this package has run against real CAN hardware, a conformance tester or a third-party implementation: the test project references `CanKit.Adapter.Virtual` and no hardware adapter.