Changelog¶
All notable changes to CanKit.Pro are recorded here. This file is generated by
semantic-release from the
Conventional Commits on main — do not edit it by hand.
1.3.0 (2026-09-30)¶
⚠ BREAKING CHANGES¶
- isotp: IIsoTpChannel.SettleAsync gained a CancellationToken parameter. Callers compile unchanged; implementers of IIsoTpChannel and code compiled against 1.2.x must be rebuilt.
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01UWRpkQzKkNDYz3WiNgWvWU
* actor: IProtocolActor.PostAsync and PostAsync
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01UWRpkQzKkNDYz3WiNgWvWU * rawcan: ICanBusService.SendConfirmed and CanBusService.SendConfirmed are now SendConfirmedAsync. Signature and behaviour are unchanged.
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01UWRpkQzKkNDYz3WiNgWvWU * isotp: a received escape-form First Frame with FF_DL <= 4095 is now dropped instead of starting a reception. Peers that emit the escape form for short lengths are no longer reassembled. * isotp: IsoTpFrameCodec.BuildFirstFrame now throws ArgumentOutOfRangeException for totalLength == 0 (it used to emit a malformed frame), and IsoTpFrameCodec.TryParsePci returns false for a CAN-FD escape-form First Frame with FF_DL == 0 (it used to return true). Callers must not announce or accept zero-length segmented PDUs. Per ADR 0001 this maps to a minor bump before v1.3.0.
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01RU3KbHNXhpyCjsn6QW9tee * j1939: J1939Spn.Classify, and with it J1939Spn.Extract, J1939Spn.FromRaw and J1939SpnDefinition.Extract, now report different kinds for unsigned 3-, 5-, 6- and 7-bit fields. A 3-bit raw 4 or 5 is now Valid (was Error) and raw 6 is Error (was NotAvailable). At 5..7 bits the five codes are now the field's top five values, where they used to fill the top five sixteenths of the range.
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_018Zzhc7N2KFbUR4mr6TrWhT * canopen: SdoUploadAsync and SdoDownloadAsync throw PeerSdoAccessException before any frame is sent when the (index, sub-index) is not declared by a description bound with BindPeerDeviceDescription. With no description bound, only 1000h:00, 1001h:00, 1018h:00 and 1018h:01 are accepted. 1003h and 1018h:02-04 are not exempt. A loaded file that omits 1000h, 1001h or 1018h rejects those objects too.
Co-authored-by: Dietmar Borgards dborgards@users.noreply.github.com * j1939tp: J1939TpOptions.Th is renamed BamPacketSpacing, and the * isotp: IIsoTpChannel gains DiscardPendingPdus(long). Source- breaking for external implementers of the interface; consumers are unaffected. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0 and no shim is introduced.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com * isotp: IIsoTpChannel gains SettleAsync. Source-breaking for external implementers of the interface; consumers are unaffected. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0 and no shim is introduced.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
* isotp: IIsoTpChannel.SendWithTransmitStampAsync returns
Task
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
* j1939tp: J1939TpOptions.Tr and the tr parameter of
J1939TpOptions.With are removed; T2 now bounds the receiver's CTS-to-first-DT
wait (its J1939-21 meaning) and the originator's post-block CTS wait is
bounded by T3. J1939TpAbortReason.UnexpectedCtsNumPackets,
UnexpectedCtsSequenceNumber, RetransmitNotSupported,
ResourceNeededForHigherPriorityProcess and ReceiverAbort are replaced by the
table 7 members; SessionAlreadyOpen's value changes from 7 to 1.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com * isotp: IIsoTpChannel gains GetReceptionsInProgress() (added as TryGetReceptionInProgress in 7099e0a, reshaped since); implementations outside this repository must add it.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com * isotp: ISubscription gains WaitToReadAsync(CancellationToken); implementations outside this repository must add it.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com * rawcan: TxConfirmation gains HostTransmitTimestamp. It is an init-only property on a record struct, so existing construction and consumption compile unchanged; the public shape changes nonetheless. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0. API approval baseline taken from the generated *.received.txt. * uds: IIsoTpChannel gains SendWithTransmitStampAsync. Source-breaking for external implementers of the interface; SendAsync is unchanged for consumers and now delegates to it. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0 and no shim is introduced. **ud IIsoTpannel gains TryReceiveWithArrival. Source-breaking for external implementers of the interface; no consumer of a channel is affected. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0 and no shim is introduced. * rawcan: CanFrameEvent gains a fourth constructor parameter. It is optional, so existing calls compile unchanged; the type's public shape changes nonetheless. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0. API approval baseline taken from the generated *.received.txt.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj * isotp: IIsoTpChannel gains ReceiveWithArrivalAsync, so any external implementation of the interface must add it. The only implementation in this repository is internal. Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump before v1.3.0, and no [Obsolete] shim is introduced.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
* j1939: J1939Spn.Extract, J1939SpnDefinition.Extract and
J1939SpnCatalog.Extract return J1939SpnValue instead of double, and the
J1939SpnDefinition primary constructor takes a trailing optional
IsSigned. Migration: double rpm = J1939Spn.Extract(...) becomes
if (J1939Spn.Extract(...).TryGetValue(out double rpm)) { ... }, or
J1939Spn.Extract(...).GetValueOrDefault() for a NaN-on-indicator
double. Reading .Value on an indicator throws InvalidOperationException
— that throw is the point: the old code silently produced a number.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
- test(j1939): pin the inferred sub-byte indicator widths, and name the 3-bit trade-off
Classify generalises the §5.1.1 tables to untabulated widths by keeping the leading group a fixed size per width class. The tabulated widths were covered; the inferred ones — 3, 5, 6 and 7 bits — were not, which is exactly backwards: a reading the standard does not state is the one that can drift without anyone noticing.
Twenty-six known-answer cases now pin each band at both boundaries. They also make the consequence of the rule visible rather than implied: because the leading group is fixed per class, the indicator fraction of the range is whatever the tabulated width of that class already spends — about 2% for a byte or wider, five sixteenths for 4..7 bits, one half for 2..3 bits.
That last case is worth a second look and is now named in the remarks: a
3-bit field classifies raw 4..7 as indicators, so a parameter genuinely
carrying eight states loses half of them. Scaling by value rather than by
leading group would cost two states instead of four. J1939-71 tabulates
* rawcan: ICanBusService.FindOverlappingFilterSubscriptions() now returns
IReadOnlyList
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj * canopen: footer, so the generated release notes would render the subject line alone and none of the migration guidance. This repository merges rather than squashes, so the footer has to live in a commit — the pull request body is never read by the analyser.
The README gains the migration section the break needs: dropping the
argument sends identical frames, Block moves 3 -> 1, and the one real
behavioural difference is at or above SdoBlockThresholdBytes, where a
download that used to pass Expedited or Segmented bypassed block transfer
as an undocumented side effect and now uses it.
* canopen: SdoTransferMode.Expedited and SdoTransferMode.Segmented
are removed from CanKit.Pro.CANopen, and SdoTransferMode.Block changes
value from 3 to 1. Neither removed member had any effect on the wire:
the expedited/segmented split is decided by the payload length on download
(1..4 bytes expedited, 5+ segmented) and by the server's initiate response
on upload. Migration: drop the argument —
SdoDownloadAsync(id, idx, sub, data, mode: SdoTransferMode.Expedited) and
mode: SdoTransferMode.Segmented both become
SdoDownloadAsync(id, idx, sub, data), which sends exactly the same frames.
The one behavioural difference is at or above
CanOpenNodeOptions.SdoBlockThresholdBytes (default 128 bytes), where a
download that previously passed Expedited or Segmented bypassed block
transfer and now uses it; raise SdoBlockThresholdBytes on the node options
if that matters. Callers that persisted or transmitted the numeric enum
value must remap 3 to 1.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
- fix(canopen)!: keep SdoTransferMode.Block at 3, and bound the expedited range by the threshold
Two review findings on the removal commit, both correct.
Renumbering Block 3 -> 1 to close the gap left by the removed members made it reuse the value Expedited carried in 1.2.x. Removing the members gives a recompiling caller a compile error, which is the loud failure this break wants — but a caller that is not recompiled, or a persisted or transmitted numeric value, supplies the literal 1 and would have gone from requesting a no-op hint to forcing block transfer. That is a real change on the wire and it hangs against a peer with no block support: the worst kind of break, silent and remote. A gap in an enum costs nothing by comparison, so Block keeps its value and the gap stays.
The public contract also stated the CiA 301 split as though it were independent of the block threshold: "1..4 bytes expedited, 5 and up segmented, and at or above SdoBlockThresholdBytes block transfer". The threshold is tested first (CanOpenNode.SdoDownloadAsync), and the options permit a threshold of 1..4, so on such a node a one-byte payload goes by block transfer and the expedited claim is false. The internal comment at the selection site already had this right; it is the public documentation that was wrong, and it now says the threshold bounds the expedited range too. Three of the five affected doc sites already carried the qualification and are unchanged.
The API approval baseline was regenerated from the test's own .received.txt; its only delta is the enum value.
Build 0 warnings / 0 errors with CI=true, suite 444/444, format clean.
* canopen: SdoTransferMode.Expedited and SdoTransferMode.Segmented
are removed from CanKit.Pro.CANopen. This supersedes the migration note on
the removal commit in one respect: SdoTransferMode.Block keeps its value
3 and there is nothing to remap. That earlier note said Block moves from
3 to 1; it does not, because 1 is the value Expedited had in 1.2.x
and reusing it would silently turn a legacy caller's no-op hint into forced
block transfer. Everything else in that note stands: neither removed member
had any effect on the wire, so
SdoDownloadAsync(id, idx, sub, data, mode: SdoTransferMode.Expedited) and
mode: SdoTransferMode.Segmented both become
SdoDownloadAsync(id, idx, sub, data), which sends exactly the same frames;
and at or above CanOpenNodeOptions.SdoBlockThresholdBytes (default 128) a
download that previously passed one of the removed modes bypassed block
transfer and now uses it, so raise the threshold if a peer cannot handle it.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
- fix(canopen): reject an undefined SdoTransferMode instead of silently picking a transport
Both entry points route "not Block" to the classic client, so a value that is not a defined member selected a transport without complaint. That is the wrong failure for an argument that can only arrive from a bug, and the removed members make it reachable: an assembly still compiled against 1.2.x supplies the literal 1 or 2 for Expedited and Segmented, and a caller following an out-of-date migration note could pass the same. Silently sending different frames than the caller asked for is diagnosed on the wire, hours later, by someone who does not know the enum changed.
SdoUploadAsync and SdoDownloadAsync now throw ArgumentOutOfRangeException for anything other than Auto or Block, synchronously, before a Task is handed back so an unawaited call cannot swallow it. The message names the removed members and says the argument should simply be dropped.
This is the code half of the review finding about the stale migration note in the removal commit's footer. It does not correct that note — the text is in an already-pushed commit message and semantic-release reads commit messages, so fixing it needs a history rewrite that is not available here. What it does is make following the stale advice fail loudly at the call instead of quietly changing the transport, which is the harm the note could otherwise cause.
Covered by Sdo_Transfer_With_An_Undefined_Mode_Throws_Rather_Than_Picking_A_Transport, a theory over the two legacy literals and one never-defined value, verified to fail on all three cases with the validation removed.
Build 0 warnings / 0 errors with CI=true, suite 447/447, format clean.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
- docs(canopen): stop the undefined-mode message from understating what the removed modes did
The message told the caller the removed members "had no effect on the wire" and that the argument should "simply be dropped". The first half is the premise of this PR and the second half follows from it, but only below CanOpenNodeOptions.SdoBlockThresholdBytes. At or above the threshold the removed members did have one observable effect: they suppressed the Auto-to-Block switch. A caller who relied on that and follows the message literally moves onto block transfer, which is the single migration step that can hang against a peer with no block support.
So the exception now separates the two cases and names the threshold as the knob for keeping the classic transport, and the remarks say explicitly why the message must not be shortened back to "drop it". The README migration section and the pull request description already carried the distinction; the exception text was the one place that flattened it.
Text only -- no behaviour change. Build 0 warnings / 0 errors with CI=true, suite 447/447, format clean.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
- docs(canopen): qualify the migration claim in the README the same way
Same overstatement as the exception message carried, in the sentence that introduces the migration example: "dropping the argument sends exactly the same frames" holds below CanOpenNodeOptions.SdoBlockThresholdBytes and not at or above it, where the removed members suppressed the Auto-to-Block switch. The section already said so under "One behavioural difference", but a reader who takes the promise at the top and skims the example has no reason to read on.
The claim is now bounded where it is made and points at the one case that changes traffic, and the code comment in the example says "below the block threshold" rather than an unqualified "identical traffic".
Build 0 warnings / 0 errors with CI=true, format clean. Markdown only.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj * rawcan: CanIdFilter.Range and CanIdFilter.Mask now throw ArgumentOutOfRangeException for bounds or acceptance pairs outside the target ID space. Code that built such a filter was matching nothing at all -- the fix is to pass CanFilterIDType.Extend for 29-bit IDs, or to correct the bound. Filters already inside their ID space are unaffected.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
* rawcan: ISubscription.Frames yields CanFrameEvent instead of
CanFrameView, TryRead has an out CanFrameEvent, and subscription
predicates and callbacks take CanFrameEvent. Reach the frame through
.Frame. On a bus not configured for echo nothing else changes; on an echo bus
a subscription withholds host echoes unless it passes includeEcho: true. Note
that the flag is host-scoped, so a protocol layer sharing one ICanBusService
with siblings must opt in and identify its own traffic itself -- every layer in
this repository now does. CanFrameEvent equality compares payload bytes
rather than the backing buffer. Per docs/decisions/0001-versioning-and-api-stability.md
this ships as a minor bump, not a major one: 1.3.0 is the first release for
which the SemVer promise holds.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
* rawcan: compare CanFrameEvent by payload bytes, and correct the stale narrative
* isotp: opt subscriptions into echoes on a shared service
* rawcan: the echo flag is host-scoped, so protocol layers opt in
* j1939tp: keep the source-address self-check behind the echo gate
* rawcan: ISubscription.Frames yields CanFrameEvent instead of
CanFrameView, TryRead has an out CanFrameEvent, and subscription
predicates are Func<CanFrameEvent, bool>. Reach the frame through
.Frame. Echo frames are no longer delivered to a subscription that did not
pass includeEcho: true; on a bus not configured for echo nothing changes.
Per docs/decisions/0001-versioning-and-api-stability.md this is a minor bump,
not a major one: 1.3.0 is the first release for which the SemVer promise holds.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_011Zd6AyAtcZApgfRC2Rkitj
Features¶
- actor: let IProtocolActor.PostAsync be withdrawn with a CancellationToken (6516b28)
- addressing: take the frame's kind into Decompose, refuse a PDU1 PGN with a low byte, and give the NAME its wire order (9d9e45e), closes #55
- canopen: add listen-only discovery and the scan on request (c24b368), closes #131
- canopen: add SdoAbortCode.InvalidSequenceNumber and ValueRangeExceeded (56df0b5), closes #39
- canopen: boot assigned slaves after the flying master wins (a63422f)
- canopen: decode a peer PDO from its live mapping or from the EDS (5571517)
- canopen: default 1F80h from the node profile and hold the master (dc5131f)
- canopen: derive the node's communication configuration from its object dictionary (196eaa8), closes #41 #40 #42 #43
- canopen: elect an active NMT master with flying master (8beed02)
- canopen: gate client SDO on a peer EDS or DCF (056fbad)
- canopen: load the object dictionary from an EDS or DCF device description (74f3c4a), closes #132 #132
- canopen: prefer the live COB-ID and mapping over the EDS (b544f21)
- canopen: raise ApplicationReset before the boot-up and send every EMCY through one ordered path (236c574)
- canopen: SdoAbortException says which side aborted (#59) (c9967c3)
- isotp): stamp a functional response with its arrival; fix(uds: note a suppressed send's window before the send, and run P2* from the 0x78's arrival (1dc74ac), closes #150
- isotp: let a channel be settled, so a look at the inbox at a deadline sees every frame that arrived before it (c3c025b)
- isotp: let a discard take the caller's stamp, so what it drops is what the caller has read (a8b54a1)
- isotp: let a functional client listen on one subscription across collections (3728387), closes #150
- isotp: let IIsoTpChannel.SettleAsync be cancelled with a CancellationToken (3b9546f)
- isotp: report the arrival instant of a received PDU (88099eb)
- isotp: report when a functional request went out, and leave out a response from before its handoff (c2dbc0b)
- j1939tp: bound the per-destination TX queue and drop cancelled entries (742b87c), closes #204
- j1939tp: serve retransmit requests, read a PDU1 PGN as the group it names, refuse an RTS allowing no packet, deliver before the event, and name the BAM spacing what it is (7130884), closes #58 #55 #144
- rawcan: carry the echo flag and receive timestamp to subscribers (7831d69), closes #23 #19
- rawcan: give the callback Subscribe an onError channel, and stop the pump from failing unobserved (11cd32c), closes #53 #53 #53
- rawcan: replace the overlap tuple pair with a named FilterOverlap carrying the shared ID range (46db7cb), closes #82 #82 #82
- rawcan: report the instant before the driver call in a confirmation (89fe4ff)
- rawcan: stamp a frame in the demux, before any subscription buffers it (4f77091)
- uds: the collected UDS findings -- busy repeat, functional addressing, and four corrections (e460d7f)
Bug Fixes¶
- actor: dispose a withdrawn PostAsync call and tidy its ownership (f9639e7)
- actor: let the withdraw transition decide a dispatch failure too (78b4cd8)
- actor: mark marshal-failure handlers as on-loop (647feb1)
- actor: measure deadlines on a monotonic clock, keep timers fair (869756d), closes #20 #21 #19 #54
- actor: release the loop count and disposables when the loop fails to start (e1dbd85), closes #209
- actor: release the token registration when PostAsync is refused (dd1a4ab)
- build: repair the XML comment that broke every build leg (ff7012a)
- canopen: abort a block-upload initiate with an invalid blksize (#59) (8109cf7)
- canopen: accept a 1016h count only for sub-indices that exist (948366c)
- canopen: accept a block transfer of exactly MaxSdoTransferBytes (#59) (6cd7632)
- canopen: allow the full 1018h identity without a peer file (8c87878)
- canopen: an accepted block-upload segment settles earlier sends (01dbd92)
- canopen: any in-range upload segment settles the earlier sends (ffd450f)
- canopen: apply a sub-block confirm's blksize to the following sub-block, not to the retransmission (2571ccf), closes #134 #133
- canopen: arm the life time before the guarding reply leaves, and the producer before a reset's boot-up (293882f), closes #141
- canopen: bound the critical event backlog behind a stuck handler (1749427), closes #201
- canopen: check a 1016h count for duplicate producers and keep every heartbeat behind the reset boot-up (f3ebfa4)
- canopen: close the review findings on the OD-driven node (f8e7915), closes #133
- canopen: coalesce event-queue wakeups (e5134f8)
- canopen: complete a block upload only once its end ack is sent (3247f27)
- canopen: confirm a damaged sub-block once; no initiate guessing in the segment phase (#39) (21656f0)
- canopen: confirm a forced reset and keep a taken-over watch (046e7a6)
- canopen: copy a foreign PDO payload before the mapping upload (3dffcfc)
- canopen: cover the flying-master branches Codecov left partial (b5fc8b2)
- canopen: do not let a dropped event keep two identical critical events apart (67d7b3e), closes #201
- canopen: drain the listen pump before a cancellation surfaces (0115d1b)
- canopen: drop a reset or claim that was queued after dispose (79abae9)
- canopen: drop the extra catch around flying-master events (ffa4a55)
- canopen: drop the poll gate again -- it is spent before the answer is known (197bc23), closes #43 #43 #43
- canopen: drop the SDO self-guard again -- it could only subtract (650c4ec)
- canopen: end the listen when its subscription ends early (42280f8)
- canopen: fail an SDO client transfer whose request is not sent (326c837)
- canopen: fill a reused 1016h slot before the count, write 1001h inside the EMCY chain, keep EMCY off the SYNC CAN-ID (b42e585), closes #133
- canopen: filter heartbeat watches with Where (8e4e496)
- canopen: fold an identical critical event only when nothing else about that producer came between (f328b10), closes #201
- canopen: fold critical events again when the event that separated them is dropped (ead89fc), closes #201
- canopen: grow a sizeless SDO download geometrically (a3ec1f5)
- canopen: guard added sub-indices, leave synchronous TPDOs to the SYNC, actuate every RPDO on a shared COB-ID (ba62a1e), closes #133
- canopen: hear echoed heartbeats and read 1000h once in the scan (05d2a4c), closes #197
- canopen: hold boot commands while a forced reset is unconfirmed (ae43e55)
- canopen: hold the write gate for a whole configuration and cap 1016h:00 at 127 (7136443)
- canopen: ignore a stray command specifier during block SDO (fa52f6e)
- canopen: ignore SDO responses that name a different object (#18) (2c86298)
- canopen: keep a producer's restart observable while guarding runs (fc249c2)
- canopen: keep boot-up and self-ignore through a detect cycle (3a79b6f)
- canopen: keep dispatching after a flying-master subscriber throws (fefeda7)
- canopen: keep SYNC and a PDO off one CAN-ID, run every reset subscriber, and chain the guarding reply (5ac1edd), closes #133
- canopen: keep the event pump running after a subscriber throws (c0d82d1)
- canopen: keep the newest settings when a dropped separator lets two timeouts fold (1238c0f), closes #201
- canopen: keep the node's own SYNC reaching HandleSync (5d02992), closes #23
- canopen: keep the settings a timeout reports in its coalescing identity (2224009), closes #201
- canopen: keep timeout and EMCY events when the queue is full (edfbc6d)
- canopen: let a configured consumer outrank the heartbeat self-drop (e2dc27f)
- canopen: let a pending confirmation, not the SDO timeout, decide (11b20ff)
- canopen: let a timeout of each kind fold, and keep event-key equality out of the patch (eaab440), closes #201
- canopen: let a timeout replace the one still waiting instead of keying it by settings (9e2f275), closes #201
- canopen: let only the latest SDO send decide, and fail on a cancel (b59407f)
- canopen: listen for heartbeats without opening a node (306360d)
- canopen: look up described PDO objects by index (513fdf1)
- canopen: make a dictionary write one transaction and re-arm event timers on Start (b9ba86a), closes #133
- canopen: never map an object of the communication profile area (0aed9d1)
- canopen: no empty catch on a late send failure, exact scan output (8a6fe82), closes #197
- canopen: pause the active master while a forced reset is held (7183668)
- canopen: put every dictionary mutation under the write gate and read an RTR on every TPDO sharing its COB-ID (5a35616), closes #133
- canopen: raise the transfer's own failure for a thrown send (af33fb3)
- canopen: re-arm the block-upload server deadline per sub-block (#17) (fd52d5d), closes #92
- canopen: refuse a truncated SDO segment instead of padding it with zeros (e39b3c2), closes #203
- canopen: reject a peer DCF commissioned for another node (ea5aff8)
- canopen: release the listen window before a stream fault surfaces (0033083)
- canopen: release the SDO cancellation registration when the transfer ends (#59) (3c051bc)
- canopen: remember a slave that checks in during a held force (ba8733c)
- canopen: remove SdoTransferMode.Expedited and .Segmented (#97) (a723b3c), closes #44
- canopen: report a $NODEID formula in a header entry as EdsParseException (378cfd7), closes dborgards/eds-dcf-net#577 #220
- canopen: report a cancelled SDO send on the background event too (12c1d34)
- canopen: report a device type only for a four-byte 1000h answer (b607135)
- canopen: report adapter send failures from the NMT queue (64e9053)
- canopen: require a confirmed cold reset and an honest snapshot (88438fc)
- canopen: resolve a typed write's type under the write gate (1a99e57)
- canopen: restore only what has a power-on source, report unreadable PDO values, and take an orphan mapping record (713370f), closes #135
- canopen: reuse the 1016h slots an NMT reset hid when the consumer array grows again (f9afa89)
- canopen: serialize peer PDO reads and skip restricted COB-IDs (3f1fca3)
- canopen: start slaves that checked in during a failed force (676f2bd)
- canopen: stop a block sub-block after its first unsent segment (0d8bfa3)
- canopen: stop a node raising its own EMCY and heartbeat as a peer's (d122d7c), closes #95 #93 #103 #94 #95
- canopen: stop reading a boot-up frame as a node-guarding response (14a60e3), closes #43 #114 #94 #43 #114
- canopen: store at the "save" write itself and see a change of state right after a direct configuration (1f81641), closes #133
- canopen: treat an SDO initiate with e=0 as segmented (0eaa3c1)
- canopen: wrap only the $NODEID NotSupportedException, not every one (fca278e)
- canopen: write a PDO configuration as one transaction on the actor loop (0ba496b)
- canopen: yield an equal claim during the detect-cycle race (0e7c34e)
- isotp: abandon a reception under way on dispose, keep tests net48-buildable (7786a2b), closes #216
- isotp: an ignored First Frame leaves a reassembly in flight alone (4e510ff), closes #27 #56
- isotp: bound a functional collection by its frames' arrival stamps, and widen three functional tests' margins (808e9c3)
- isotp: bound approximated SendConfirmed, make Dispose safe, guard DatagramReceived (8b0fcb0), closes #202 #205 #206
- isotp: cut stale responses off at the last frame's handoff, not the first's (c12294c), closes #147
- isotp: drop what arrived before a discard unanswered, and reject a response that began before the request (b7e054f)
- isotp: ignore a First Frame that fits a Single Frame, take flow parameters once, withhold self-echoes, and discard inline on the actor (495d959)
- isotp: keep a frame from after the deadline for the next collection, and report an ended subscription instead of returning empty at once (2bb7a00), closes #150
- isotp: keep every First Frame read ahead of the actor in progress, not only the latest (583a79e)
- isotp: keep the abort of a reception that began after a discard (464b3cc)
- isotp: opt subscriptions into echoes on a shared service (be1685b)
- isotp: publish a First Frame on arrival, with its data, so a waiter sees it before the actor does (a490e0f), closes #143
- isotp: pump the subscription on demand, so a buffered First Frame is seen before the reader task runs (bcd56b1), closes #143
- isotp: read the listener's buffer against now, not against a negative window's past (976fb04)
- isotp: read the listener's buffer without a timer for a zero window (e9ce1fc), closes #150
- isotp: record the IIsoTpChannel member added in 7099e0a as the break it is (5a21275)
- isotp: refuse a listener window beyond a timer's reach before taking what was carried over (92b2ae4)
- isotp: reject an escape-form First Frame whose FF_DL is not above 4095 (94f7986), closes #207
- isotp: reject zero-length First Frames in IsoTpFrameCodec (52d0e95), closes #207
- isotp: report the first frame's handoff instant with a send, and cut stale responses off there (19203ee)
- isotp: stamp a PDU when its last frame arrives, not when reassembly ends (25e8146), closes #102
- isotp: stamp a received PDU with its first frame's arrival, and expose a reception in progress (7099e0a)
- isotp: stop caller-side pumping once disposed and withdraw announcements last (ca394c7), closes #216
- isotp: take the discard stamp and drain the subscription under the pump lock (0cb0122)
- isotp: validate CAN_DL of received frames, bound reassembly by MaxReceivePduLength, bind the STmin timer to its transfer (1e011f1), closes #27 #26 #25 #27 #26
- isotp: withdraw published receptions when the actor is already gone, cover the diff (3fa4508), closes #216 #94
- isotp: withhold echoes on one identifier only when the extension byte cannot tell the directions apart (c747766)
- j1939: a peer claiming the vacated address ends the marker (ca18105)
- j1939: answer a Request for Address Claimed with the Cannot Claim already waiting (fe277da)
- j1939: answer a Request for Address Claimed, and re-scan the arbitrary field after losing a claimed address (522b6ae), closes #34 #35 #34
- j1939: back off before Cannot Claim and a re-claim, fault a second claim in arbitration, and send without a pool hop (568dd5e), closes #58 #121
- j1939: bound the vacated marker to the claim it belongs to (483324d)
- j1939: cannot-claim an equal NAME on the same address (a4a2dd3)
- j1939: classify untabulated sub-byte SPN widths by terminal codes (9b3b783), closes #99
- j1939: complete the Cannot Claim handoff for the claim that started it (083fbca)
- j1939: consume the ledger before the source-address drop, and direct only to an address the node holds (629c55f), closes #140
- j1939: fault a lost claim only after the Cannot Claim handoff (b6c4ee6)
- j1939: fault a lost claim only once its Cannot Claim is on the bus (059c42d)
- j1939: filter live claim echoes with Where (37dfb2d)
- j1939: invalidate a lost address at once, keep the claim in hand through the backoff, and drop a Cannot Claim a new claim overtook (8b1bf4c), closes #153
- j1939: keep a frame addressed to this node out of the self-drop (33301e4)
- j1939: keep a timed-out claim echo from poisoning the retry (ba413e6)
- j1939: keep claim-echo markers from outliving the send (0c2606f)
- j1939: keep the node's TP reader running after a reassembly abort (13d18f2), closes #195
- j1939: keep the vacated address across further claim rounds (654c4a7)
- j1939: read and write the NAME of an address claim in wire order (fa832ba)
- j1939: recognise the address being vacated while a claim is in flight (0a29766)
- j1939: recognise the node's own echo by content, not by the address it vacated (79e85bb), closes #119 #121 #119
- j1939: report SPN indicator ranges instead of scaling them (#98) (e6afc0a), closes #99 #37 #99 #97
- j1939: settle every Cannot Claim still in flight when the node is disposed (7550d3d)
- j1939: stop a node raising its own broadcasts as peer traffic (f5cf268), closes #95 #95 #94 #94 #94
- j1939: take the claim backoff from the low byte of the NAME's sum, and read the lost address in the handler (35c8799)
- j1939: tie a delayed Cannot Claim to its loss, and start a backing-off round on a request or a contest (99cc809)
- j1939tp: answer an already-canceled send with a cancellation (8155baf)
- j1939tp: apply a retransmit request stashed mid-block as soon as the outstanding packet is confirmed (eb331b6)
- j1939tp: check the destination of every TP.CM control frame (#30) (7eeb4b1)
- j1939tp: classify packet 0 and any repeated packet by table 7 (780ace3), closes #145
- j1939tp: count only packets up to the outstanding one as sent while a block drains (ebb24b3)
- j1939tp: fault the previous BAM when a new one arrives (e48a1c8), closes #169
- j1939tp: hold the CTS-to-first-DT window to T2, send table 7's abort codes, release the send's token registration (8a21aa8)
- j1939tp: keep the duplicate-send error when the destination is full (f6c4de5)
- j1939tp: keep the source-address self-check behind the echo gate (15aaf1c), closes #93
- j1939tp: publish a send's outcome and release its slot in one step (8924562)
- j1939tp: read a retransmit request past the byte wrap, accept EndOfMsgAck after a partial retransmit, and state the event's threading (ff02cc1)
- j1939tp: reserve the queue slot before copying the payload (eec0bbb)
- j1939tp: reserve the send limit at admission, before the actor is posted (97939a5)
- j1939tp: roll back the admission slot on every failure and drop dead queue code (3b8efe1)
- j1939tp: send nothing outside table 7 (38c0461)
- j1939tp: send to one destination at a time instead of interleaving sessions (#32) (0b5a2ad)
- j1939tp: skip queued sends that were completed before their turn (cacec4c)
- j1939tp: tell a retransmit request from the next block by the highest packet ever sent (b32ca2b)
- j1939tp: unlink queued sends in O(1) instead of shifting a list (57115ae)
- rawcan: cancel the abandoned transmit on timeout, guard test disposal (ca43189), closes #216
- rawcan: claim a pending send by completing it, not by asking whether it is complete (f75b40f), closes #92
- rawcan: compare CanFrameEvent by payload bytes, and correct the stale narrative (5f2a0e1)
- rawcan: hand the driver a private frame copy, honour caller cancellation, fix Dispose races (163b41b)
- rawcan: reject CanIdFilter ranges and masks outside their ID space (45e10c7), closes #53 #53
- rawcan: reject undefined CanFilterIDType in CanIdFilter (c20f361)
- rawcan: report the instant the driver accepted a frame (d75876e), closes #92
- rawcan: stamp the approximated send at driver completion, not at resumption (2c7fa4f), closes #92
- rawcan: stop a cancellation from waiting on an unrelated send's driver call (2a87013), closes #92 #24
- rawcan: stop an expired pending send from poisoning the echo FIFO (cf24dc0), closes #24
- rawcan: take the arrival stamp before the pending-send lock (fc68498), closes #92
- rawcan: the echo flag is host-scoped, so protocol layers opt in (30eed7c), closes #23
- reliability: coalesce BusStateMonitor's error-frame rechecks (a68994e), closes #22
- test: keep twenty gaps after trimming the warm-up, not nineteen (dc47793)
- test: size the periodic rate bound by its error term instead of picking a statistic (92fb9c8), closes #101
- uds: a functional call queued behind another does not send after dispose, and a positive response must echo the sub-function (2769a4b)
- uds: anchor a functional request's window at its transmission, however late that was confirmed (2da4e3a)
- uds: anchor the functional window at the driver's acceptance, and take no 0x78 from before the handoff (6006623)
- uds: anchor the functional window when the collection leaves by exception (d7cefc1)
- uds: bound "began before the request" by a reading taken before the send, not by the transmit stamp (c9af8af), closes #143 #92 #143
- uds: bound every duration in the client options at a timer's reach (5cb50c0), closes #150
- uds: bound the functional client's windows at creation as a collection window is (fc86326)
- uds: correlate a functional RequestFileTransfer on its modeOfOperation (0d6fa8b)
- uds: correlate functional answers on the echoed parameters, and wait out a suppressed send's window before a same-service request (e514791), closes #150
- uds: correlate functional answers to the request, require a window for an unsuppressed TesterPresent, carry the busy-repeat options in With (7cbebdc), closes #150
- uds: correlate the DID-echoing services 0x24, 0x2C and 0x2F on the functional path (534b1a5)
- uds: discard stale replies before a suppressed send, as before an answered one (5672520)
- uds: end P2 with the response's first frame, and treat an all-zero seed as unlocked (820757b)
- uds: enforce P2 against the response's arrival, not the client's scheduling (cbdbc62), closes #92
- uds: extend a suppressed send's window on NRC 0x78, and keep every functional request's window open for the rest of its P2 (29b5bab), closes #150
- uds: gate download size check on DFI and reject oversized sizes (e494a60)
- uds: give the functional client one listener per service for the whole window, and validate the collection window before sending (01ece81), closes #150
- uds: hold the handoff cutoff with the window, for the listener that reads a 0x78 after the anchoring (0916c20), closes #150
- uds: keep a suppressed send's window per service, on both clients, and refuse a functional multi-DID read (15882ec)
- uds: keep the functional listener through a send whose confirmation outlasts the window (edba9e4)
- uds: leave no window behind a request the channel refused before transmitting (cfec2b8)
- uds: note a functional window before the send, keep a cancelled wait's remainder, drain before ending a wait, and correlate 0x2A on its identifier (7269ce3), closes #150
- uds: note a suppressed send's window again when the send leaves by exception (e1fdea2), closes #150
- uds: only decode download memorySize when DFI is unencoded (5bef193)
- uds: read the inbox before declaring a timeout (7cf8d8e), closes #92
- uds: read what the functional listener's subscription buffered before retiring it (36d8017)
- uds: refuse a collection window beyond a timer's reach before anything is transmitted (6728759)
- uds: reject a download whose memorySize disagrees with the payload (7b68765), closes #166
- uds: reject a download whose memorySize disagrees with the payload (#182) (cf98b2d), closes #166
- uds: report cancellation when the P2 budget is already spent (ba73ac6)
- uds: restart the functional listener when anchoring a window after a confirmation that outlasted it (db58008)
- uds: retire the refused send's listener before the window is put back (a2b68a6)
- uds: revive no functional window for a 0x78 collected after the request's P2 (1d0b046), closes #150
- uds: revive no window for a 0x78 from after its end, and correlate WriteMemoryByAddress on its address and size (ef55548)
- uds: revive no window for a 0x78 of the waited service itself from after its end (0d7266b), closes #150
- uds: revive no window for a late 0x78 heard while another service's wait-out runs (675e29b), closes #150
- uds: route a heard 0x78 to its own service's window, survive a queued transport fault in the drain, and take the conservative reading on a cancelled functional wait (0319c25)
- uds: route a stray 0x78 to its service's window, start no listener for a window already over, and assert the functional windows as lower bounds (79c3ea1)
- uds: serialise functional requests, and reject a negative busy-repeat count (77368d2), closes #150
- uds: settle and route what the channel holds on an aborted request's discard (367315c)
- uds: settle the channel before reading the inbox empty at a deadline (2a697de)
- uds: start P2 at the request's transmit stamp, not on the client's clock (ab7be43), closes #92
- uds: start the functional send's listener whatever its window reads (8e2d181), closes #198
- uds: subscribe the functional listener before the send, retire it under the windows lock, and route a stray 0x78 from before the handoff (9c4a976), closes #150
- uds: take the pre-send discard's stamp before routing what the inbox holds (69b38f2)
Performance¶
- rawcan: copy each payload once per frame, and stop copying echo payloads at all (458ff08), closes #53 #53
Build & Dependencies¶
- deps: Bump coverlet.collector from 10.0.1 to 10.1.0 (5c02f00)
- deps: Bump EdsDcfNet from 1.13.0 to 1.14.0 (4a14b18)
- deps: Bump Polyfill from 11.3.0 to 11.4.0 (95ce309)
- deps: Bump Polyfill from 11.4.0 to 11.4.1 (34da8c2)
- deps: Bump the test-tooling group with 1 update (933c984)
- fix the red net48 leg with Polyfill instead of a hand-rolled shim (201ff63), closes #83 #81 #83 #81 #83
Documentation¶
- a defect the branch caused is closed in the pull request, not filed (4493835), closes #105 #101 #92
- accept either spelling of an angle bracket when shortening links (9f4eab7)
- actually apply the merge-strategy correction to CLAUDE.md (04597e0)
- add CLAUDE.md with the working agreement (359e550), closes #93
- add CLAUDE.md with the working agreement (4dd1d2c)
- add the scope rule, which is the one that was broken hardest (5c45445)
- add the working-practice retro for the 12/13 September issue wave (baa775e), closes #92 #102
- adr: record that #23 unblocks the release dry run (6882a26)
- align the worked example with the inverted exception, and say who owns the call (e30b632), closes #105 #105
- an authorised late push revokes the merge-ready signal (07fe5e0)
- audit delay and sleep sites before further conversions (fad2c42), closes #114
- bring the retro up to date with the half of the wave that came after it (9e05009), closes #104 #107 #108 #101 #104 #108 #106 #104 #106
- build: cover dirty trees and source archives in the 0.0.0 guide (4febdb1)
- build: explain how to identify a local 0.0.0 build (e69b18a), closes #212
- build: point releases at the embedded commit and fix the C# example (c4e1fd2)
- canopen: bind flying master and boot-up to CiA 302-2 v4.1.0 (c025c3d)
- canopen: describe NmtState and the reset commands as the node now implements them (09084ec), closes #59
- canopen: describe the package as the object dictionary now drives it (88b73fb), closes #59
- canopen: drop "static and dynamic PDO mapping" from the package one-liners (b9b1cd7)
- canopen: keep the bus scan listen-only by default (ebeca4b), closes #131
- canopen: record the answers that close the master/tool scope (b2166f6), closes #131 #174 #163 #164
- canopen: record the assumed CiA 302-2 flying master binding (73e090f)
- canopen: SdoFrames no longer claims block transfer is out of scope (061759a), closes #59
- canopen: specify the device-role scope as FR-CO-013..024 (20f0e89)
- canopen: state that a silent scan target also gets the timeout abort (430fe50)
- canopen: the guarding consumer's comment no longer describes the old state-change heartbeat (dbd422a)
- carry the exception through the out-of-scope procedure (b087366)
- ci: correct what the release job split actually removes (9ed717d)
- cite the durable record, not commits that never entered main (0ddb8e9), closes #104 #107
- close the three remaining holes in these rules in one pass (1e2f3e3)
- correct the base-merge half of the sequencing rationale, and date it (05f4e09), closes #100 #101 #106 #85 #85
- correct the merge semantics in the pull-request template too (6d33e07)
- correct the merge-strategy claim, in CLAUDE.md and at its source (f41d465), closes #91 #90 #89 #93
- correct the release runbook and give it a recovery path (2e43e1e), closes #47
- correct the stale counts and the broken table in the retro (008a971), closes #93 #96 #97 #98 #100 #101 #104 #107 #108
- correct the UDS actor claim and the FR-RAW-052 status in arc42/SRS (f371f94), closes #225
- die Master-/Tool-Vorlage von den bestehenden Dokumenten aus verlinken (d5b2900)
- drop review history from code comments and say what a comment is for (b8a82df), closes #N #211
- drop the maintainer's personal address from the policy files (696fc81)
- five defects found by reading the whole file instead of the diff (c5519db)
- fix the category claims the retro's own evidence contradicts (36eb789)
- generate the API reference from the XML doc comments (a756368)
- give the one-pull-request rule the reason it actually has (15e2094)
- hide the edit link on generated API pages (17426b6)
- isotp: say what SettleAsync does when called on the channel's own actor (8172826)
- j1939tp: add the missing summary to TxCompletion's constructor (99a90f5)
- j1939tp: describe Tr as the node's own response obligation in FR-TP-032 (77583b9), closes #58
- keep FR-RAW-005 marked as open in the arc42 overall assessment (3700f2a), closes #225
- let NFR-010 factories wrap the layer directly below them (7cb12b8)
- limit the Actor validation claim to the modes each test uses (6e34911)
- list IsoTp's L2 dependencies and sync SRS CI/branch constraints (7493f60), closes #225
- make the generated API pages read like prose (bb94534)
- Mapping-Bereiche und eigene Node-ID im Master-Zuschnitt (8c98e3b)
- measure completeness against the requirements, not the issue tracker (cedfd0a), closes #94
- move CLAUDE.md to its own pull request (a720ffd), closes #96
- name the actual failure behind #105 in the chronology (f4b12bb)
- name the four contradictions by commit, and stop numbering the instances (9e64e18)
- name the real echo double and describe the CANopen peers as they are (df9c1d7)
- note the unflagged echo world beside the Virtual IsEcho candidate (8b79236)
- order the scope questions, causality before urgency (a1d4323)
- rawcan: add the 1.2.x migration section, and carry the breaking-change footer (ad27f94)
- rawcan: correct four claims the echo opt-in falsified, and cover J1939 arbitration (c9ed350), closes #23
- rawcan: record why SendConfirmed keeps Transmit inside the pending-send lock (1bba7d7), closes #53 #53
- reconcile the split exception with the no-follow-up rule (72a572d), closes #105
- record that 1.3.0 is the first stable release (a9b6ff1), closes #61
- record the #118 P2 first-hop measurement (07d5c96)
- record the macOS P2 timeout seen on the audit PR (d9fb37c)
- record the nuget.org withdrawal as done, and #23's default (714990f)
- record the verification rules the last wave was missing, and serialise pull requests (38e1006)
- reviews: a read-only record needs no wiring, and inhibit time is not wiring (cd936bf), closes #127
- reviews: COB-ID-Steuerbits und PDOMapping-Attribut; 1200h-Befund zurückgewiesen (c96e656)
- reviews: confirm both halves of #38, not only the server one (ac061ab), closes #127
- reviews: den ro-Freibrief auf das einschränken, was die Norm hergibt (7d25932)
- reviews: die Master-/Tool-Rolle als Vorlage zuschneiden (92ec4c4)
- reviews: die Regel hinter 20/21/22 als eigener Posten, statt vierter Fall (1325a77)
- reviews: EntryWritten ist eine halbe Naht, nicht die Naht (47b57df)
- reviews: fix the claims themselves, not the text under them (bf9246f), closes #127
- reviews: fünf Codex-Befunde, bei zweien gibt die Norm die bessere Antwort (f944820), closes #38
- reviews: Heartbeat-Records und 1001h/EMCY, mit korrigierter Herkunft (b7664f5)
- reviews: Master-/Tool-Zuschnitt an die Entscheidungen vom 26.09. binden (4fd048f)
- reviews: n-tes-SYNC-Verhalten und Reset Communication (Codex auf #129) (899d183)
- reviews: Posten 14 entschieden - Schreibzugriffe werden durchgereicht (e586fe9)
- reviews: Posten 23 am Kriterium der erfolgten Änderung statt am Zugriffsweg (bfb60aa)
- reviews: Posten 23 auf angenommene Schreibzugriffe einschränken (ac61057)
- reviews: Postennummern durch Benennung ersetzen, eine falsche Zahl korrigieren (ae963a5)
- reviews: put the 2026-09-10 repository review on main (40e6f32), closes #17 #18 #25 #36 #38 #43
- reviews: record the CANopen scope decision and what it changed (50bc836), closes #127
- reviews: retract the stale conclusion instead of linking past it (67d87fb), closes #127
- reviews: Runde 1 von 2 - Übertragungsart 01h, Nicht-PDO-COB-IDs, Bitlänge (46cfee6)
- reviews: Runde 2 von 2 - FEh/FFh und das 1014h-Layout; 1005h-Bit-31 festgenagelt (9c94273)
- reviews: sagen, welche Rolle dieser Zuschnitt zuschneidet (81dc666)
- reviews: separate 1200h from the PDO-engine item (476b7cf), closes #127
- reviews: settle the CANopen scope questions against the CiA 301 text (356c5d9), closes #38 #39
- reviews: SYNC-/EMCY-Records, Reset Node, Abort nur bei ro-freien Einträgen (5025867)
- reviews: take back three over-readings of the CiA 301 text (1045ccb), closes #127
- reviews: the same over-reading, twice more, in the correction itself (139a7b4), closes #127
- reviews: vier Befunde am Normtext nachgeprüft, zwei eigene dazu (9ea6b5c)
- reviews: vier Lücken in der Postenliste schließen (Codex auf #129) (f21172f)
- reviews: vier Prüffragen je Posten - die Ursache statt der nächsten Instanz (a886ebf)
- reviews: Widerspruch in Posten 19 auflösen, Gegenrichtung als Posten 20 (b682e00)
- revoke the merge-ready signal when its state stops being true (6484fa4)
- reword NFR-010 to the factory model the L3/L4 packages actually follow (0aab7d2), closes #226
- rewrap the paragraph the previous commit left over-long (50c7c02)
- samples: dispose the SemaphoreSlim in CanOpenQuickstart (c879798)
- samples: make the quickstarts beginner-friendly and add pro extras (ffeba6d)
- say what the STmin and bus-state tests actually run on (1a09ebb)
- scope by causality, and keep Dependabot out of the one-PR count (8db8b5c)
- separate non-timer waits from the clock seams (8e465c0), closes #114
- separate the chronology's entry count from its claim count (702f986)
- split lock and mailbox waits out of the clock list (4f03109), closes #114
- SRS, Normlücken und README auf die Master-Entscheidungen nachziehen (d906a77)
- state in every package README what is validated and what is not (ffd5efe)
- state plainly that the release pipeline cannot be tested before 1.3.0 (ee57c7e), closes #23
- stop restating counts the chronology already owns (a073290), closes #109
- sync arc42 and SRS with the tree (net10.0, ISO-TP shipped, default branch main) (806b133), closes #173
- test: stop crediting the STmin probe with pinning the interval (82ee4f2), closes #113
- the split is for problems this pull request did not cause, and nothing else (c25dc89), closes #105
- uds: say which functional services are correlated on the positive SID alone (72e0b82)
- write the merge-ready signal and two verification rules into the agreement (7c4622a), closes #104 #107 #109 #109 #106 #92 #104 #106 #107
Refactoring¶
- actor: add an internal ScheduleAt for fixed deadlines (0e1e867), closes #171
- actor: answer two CodeQL findings on this branch's new code (d49f017)
- actor: give the loop count to the type that owns it (ea7a45e)
- canopen: add a write-gate-waiters test seam to ObjectDictionary (31e664c), closes #171
- canopen: compare critical event keys through a tuple and skip needless null checks (78e7fb8), closes #201
- canopen: dispose the discovery subscription with using (27134f3)
- canopen: filter the loader's loops with Where and join the fixture path in two steps (f8946b4)
- canopen: split the heartbeat into producer and consumer (01181fe)
- isotp: dispose a clocked window without the actor's help (cfe03a4), closes #183 #171
- isotp: dispose a clocked window's source on its actor (482f7d1), closes #171
- j1939: open the node's TP channel through a test seam (e3e1a33), closes #195
- j1939: read the periodic anchor off the actor's clock (824dce4), closes #92 #92
- j1939tp: accept an injected actor so timers share the caller's clock (a986d46)
- j1939tp: drop frames the actor reaches after dispose began (5f84e17), closes #183 #171
- j1939tp: give EndTx one queue-cleanup path and cover the empty tail (1034e2a)
- j1939tp: order a borrowed actor's dispose and bound its wait (e949614), closes #183 #171
- j1939tp: wait for a borrowed actor's session cleanup on dispose (16c2c5c), closes #183 #171
- rawcan: expose the callback subscription's delivery pump to tests (8c3b38e), closes #171 #171
- rawcan: name ICanBusService.SendConfirmed SendConfirmedAsync (3ac00cb)
- uds: add request-lock observables for tests (d5edc88), closes #171 #171
- uds: arm the P2 and window timeouts at their deadlines (8068815), closes #171
- uds: fold the pending-response check CodeQL flagged into one predicate (a09fceb)
- uds: leave the actor's timeout source undisposed (b802ff6), closes #171
- uds: measure and wait out P2 on an injectable clock (d301db3), closes #171 #171
1.2.3 (2026-09-10)¶
Build & Dependencies¶
- deps: Bump the test-tooling group with 1 update (aa94904)
1.2.2 (2026-09-10)¶
Bug Fixes¶
- only deploy docs to Pages from main (0a84b78)
Documentation¶
- add the project website (MkDocs Material on GitHub Pages) (01bfdcf)
1.2.1 (2026-09-10)¶
Build & Dependencies¶
- deps: drop unused dependencies from CanKit.Pro.Reliability (f40b15c)
Documentation¶
- align shipped documentation with the 1.2.0 release (5f48379)
- changelog: repoint commit links after the history rewrite (8ed80f6)
- make the XML doc comments English-only (0bf8047)
- mark the 2026-07-14 review as external context (649cde0)
1.2.0 (2026-09-09)¶
Features¶
- drop VENDOR (moving to a separate internal repo), publish the rest of L3/L4 (01c8ea4)
1.1.0 (2026-09-09)¶
Features¶
- rawcan: add callback-style Subscribe(onNext, predicate) convenience API (d718a3a)
Bug Fixes¶
- ci: resolve release-config presets via import.meta.resolve (5676591)
- ci: use a bypass-eligible PAT for the release push (ca198bd)
- rawcan: skip pump join when disposing callback Subscribe from onNext (771ad11)
- rawcan: stop callback pump after self-dispose (80722d5)
- release: revert conventional-changelog-conventionalcommits to 9.3.1 (c5bf3ce), closes #2 #15 #2
Build & Dependencies¶
- deps: Bump conventional-changelog-conventionalcommits (#2) (4f2ebd8)
- deps: Bump coverlet.collector and 2 others (#8) (140fa3b)
- deps: Bump Microsoft.Bcl.AsyncInterfaces from 10.0.11 to 10.0.12 (#9) (3379766)
- deps: Bump System.Memory from 4.5.4 to 4.6.3 (#10) (f9d4c91)
- deps: Bump System.Threading.Channels from 10.0.11 to 10.0.12 (#11) (bdb8eff)
- move to .NET 10 LTS ahead of net8.0 EOL (72c3562)
1.0.0 (2026-09-09)¶
Features¶
- establish CanKit.Pro as a standalone product on top of CanKit (713fdc8)
- migrate the full L2-L4 stack from the legacy develop branch (02e3753)
Bug Fixes¶
- build: add the Fallback version strategy so an orphan branch versions (e12bc1b)
- build: give GitVersion a base version so a fresh repository builds (507a565)
- build: remove illegal double hyphen from an XML comment (4b17afa)
- build: run GitVersion in the pipeline instead of as an MSBuild task (5d130e8)
- test: let the TX-confirm double declare the echo capability it models (bc541a2)
- test: resolve the three compile failures the L3/L4 migration surfaced (cfbf994)