Every captured commit receives deterministic security triage and a separate communication-quality score. Security candidates and broader second-pass signals receive full-patch Ollama analysis.
Message quality measures whether a commit identifies its scope, purpose, rationale, testing, and supporting references. It does not change the security-severity score.
This commit simply updates the 'repository' web links in 15 package metadata files from GitHub to a self-hosted Forgejo instance. It does not change any program code, build logic, dependencies, or security behavior. There is no security is…
This commit fixes a small accounting bug in how the Lightning wallet estimates the size (and therefore transaction fee) of a special Bitcoin transaction that sweeps funds back to the user after a channel closes. The old code always assumed…
debug assertion failure possible in development/testing buildstransaction weight/fee estimate overestimation up to 3 WUconstant replaced with per-descriptor length computation
This commit changes the project's internal code-review workflow. It stops automatically assigning a human reviewer when a pull request is opened; instead, contributors must manually click a button to request a reviewer after first addressi…
This commit fixes a bug in LDK's Lightning channel reconnection logic after a splice (a way to resize a channel's on-chain funds). If one peer had already received the splice signatures but the other had not, and then they disconnected and…
Protocol-state inconsistency on reconnection after splice signature exchangePotential channel stall/force-close due to quiescence not being exited before commitment updateFuzzer-discovered edge case in Lightning splicing retransmission
This commit is a code cleanup (refactor) in the Lightning Dev Kit library. It moves existing payer key-derivation logic into shared helper functions so that future 'payer proof' features can reuse the same code. The change does not appear …
Refactor only: moves existing key derivation/verification logic into helpers without changing algorithmsAdds new public API `Bolt12Invoice::derive_payer_signing_keys` for payer proof key recoveryNo mention of vulnerability, bug, CVE, security fix, or exploit in commit title/message
This commit changes a CI workflow for the rust-lightning project. It stops trying to push new fuzz test inputs directly to a corpus repository from automated test runs, and instead uploads them as a temporary artifact that a separate sched…
This commit adds partial support in the Lightning Dev Kit node software for receiving and temporarily holding multi-part trampoline payments, then deliberately rejects them once all parts arrive because full outbound forwarding is not yet …
New trampoline forward handling path accumulates MPP parts before rejectingDebug assertion guards first-HTLC failure in MPP mergeTODO comment flags possible MPP inconsistency in next_node_id across trampoline parts
This commit changes the project's automated reviewer-assignment workflow to stop using a long-lived secret token and instead request a short-lived authentication token from the Forgejo CI service. This is a security-hardening improvement: …
Removal of long-lived repository secret from CI workflowAdoption of OIDC-based short-lived token for API authorizationWorkflow runs in pull_request_target context with no code checkout
This commit only adds new fuzz-testing commands to an existing test harness. It lets the fuzzer temporarily block and then re-enable the local node's own signing operations during simulated channel failures. There is no change to productio…
This patch fixes a bug in the Lightning Dev Kit where a delayed message from a peer could accidentally force-close a live payment channel. During a failed 'splice' (a way to resize a channel), the peer might already have sent a signature f…
Force-closure of a live Lightning channel due to stale signature validationRace condition between splice cancellation and in-flight commitment_signedIncorrect signature validation against post-abort channel state
This commit only changes a CI script to pin a dependency version so older Rust toolchains can still build the project. It is a build-maintenance fix with no security relevance.
This commit fixes a remote denial-of-service bug in rust-lightning's LSPS (Lightning Service Provider Specification) code. An attacker could send a specially crafted date string from before 1970 (like "1900-01-01T00:00:00Z") in certain pee…
Remote-triggerable panic (DoS) via peer-controlled inputInteger conversion panic: i64 negative timestamp coerced to u64 with .expect()Input validation bypass: serde transparent deserialization skipped custom parser
This commit fixes a validation bug in how Lightning Dev Kit checks 'fake' short channel IDs (SCIDs) used for routing tricks like phantom and intercept payments. The old check compared only the lowest byte of the vout field, so an attacker …
Input validation bypass in fake SCID checksType-cast truncation bug (u16 to u8) leading to incorrect equality checkPotential for spurious HTLCIntercepted event generation
This commit removes an old cryptographic nonce from the data carried inside Lightning "blinded paths" used when sending BOLT 12 offers and refunds. The nonce is no longer needed because a newer "payer metadata" field already carries the sa…
Removes a redundant nonce from blinded-path context, relying on payer metadata for invoice authenticationRetains and enforces payment_id matching to prevent cross-payment invoice delivery over captured blinded pathsMaintains backward-compatible persistence of the nonce for downgrade/retry scenarios
This commit changes how BOLT12 invoices are verified in the Lightning Dev Kit. Previously, some invoices could be verified using a nonce stored in the blinded reply path context. Now, the nonce is always included inside the encrypted payer…
BOLT12 invoice verification now depends only on data inside the invoice request/refund, reducing reliance on external contextRemoves a verification path (verify_using_payer_data) that used reply-path context instead of invoice-contained metadataBreaks backward compatibility for prior-version invoice requests/refunds with blinded paths, causing payment failures
This commit fixes a bug in how Lightning Dev Kit describes anchor outputs when preparing transactions for external wallets to sign. Previously, for a type of anchor tied to a specific channel key, the code returned the raw 'witness script'…
Incorrect scriptPubKey in PSBT witness_utxo metadata for anchor prevoutsPotential wallet/signer validation failure when signing fee-bumping transactionsRisk of misidentification of on-chain anchor output during CPFP/RBF bumping
This commit changes a fuzz test (a randomized testing harness) so it no longer crashes when a simulated splice-funding signing event becomes stale. The change only affects test code, not the production Lightning library, and it ignores an …
Error-handling change in fuzz targetReference to tx_abort invalidating queued signing eventsNo production code modified
This commit is a pure code cleanup: it renames internal Rust macros from impl_writeable_tlv_based* to impl_ser_tlv_based* across many files. The generated serialization and deserialization code is unchanged, so there is no functional or se…
This change is a developer convenience tweak for the project's internal fuzz-testing programs. It adds an environment variable switch (LDK_FUZZ_SUPPRESS_LOGS) that lets automated fuzzing runs stay quiet, while keeping normal manual runs ve…
No changes to production library codeNo changes to parsing, serialization, or cryptographic codeOnly affects fuzz target harness logging behavior
This commit only fixes compiler warnings that appear when building the project's fuzzing test harness. It removes one unused import, narrows three conditional compilation flags so they don't conflict during fuzz builds, and reduces the vis…
Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.
Lower-priorityMerge PR 'Only fetch TXIDs instead of entire block during gossip verification' (#4846)by Matt Corallo · ebe7a447 · Aug 5, 2026 · 5 filesMessage 91 · StrongTriage 0Details
Commit message · Matt Corallo
Merge PR 'Only fetch TXIDs instead of entire block during gossip verification' (#4846)
from gossip-verify-rpc into main
Reviewed-on: https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4846 Reviewed-by: Matt Corallo <matt@noreply.git.rust-bitcoin.org>
91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityAdd test framework coverage of `Listen` block connection replaysby Matt Corallo · bf6ad23e · Aug 5, 2026 · 2 filesMessage 83 · StrongTriage 0Details
Commit message · Matt Corallo
Add test framework coverage of `Listen` block connection replays
While this should generally be equivalent to receiving a block duplicatively via the `best_block_updated` + `transactions_confirmed` methods, its good to add explicit test coverage for the newly-supported (but always documented...) connection mode.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Lower-priorityUpdate functional test block connection to detect block replaysby Matt Corallo · 477facb4 · Aug 5, 2026 · 3 filesMessage 83 · StrongTriage 0Details
Commit message · Matt Corallo
Update functional test block connection to detect block replays
In cases where we replay a block, the functional test framework shouldn't consider it a new block and re-add it to the tracked blockchain in `Node`s.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Lower-priorityCorrect HTLC confusion on unrevoked counterparty commitment txsby Matt Corallo · f06a08a6 · Aug 4, 2026 · 2 filesMessage 73 · AdequateTriage 8Details
Commit message · Matt Corallo
Correct HTLC confusion on unrevoked counterparty commitment txs
When we see an HTLC on an unrevoked counterparty commitment transaction we check if it has a corresponding `HTLCSource` when deciding whether it is likely from a revoked counterparty commitment transaction. This is insufficient, however, and can result in us assuming that an HTLC is on a revoked counterparty commitment (and thus is safe to fail back based on a loose HTLC match) rather than on a live one.
Here we correct this check and also expand several debug assertions that validated the detection of the claim style against the HTLC type into full-blown assertions. If we end up hitting these, they're almost certainly an indication that something has gone horribly wrong and either keys have leaked or the node software is confused and continuing would be unsafe.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Why it was queued
defensive validation
AI review queuedAvoid oversized relayed failure messagesby Matt Corallo · 6b1dfb1a · Aug 4, 2026 · 1 fileMessage 78 · AdequateTriage 5Details
Commit message · Matt Corallo
Avoid oversized relayed failure messages
A downstream peer could send a maximum-sized update_fail_htlc without attribution data. Adding attribution data while relaying the failure made the message exceed the Noise framing limit and panic during encryption.
Drop the attribution data again when adding it would push the relayed failure over the wire limit, while preserving attribution for packets that fit. The message length is derived from serialized_length on the message and on the attribution data itself rather than from hardcoded field sizes, which also lets us replace a stale assertion on the maximum failure data length. Add a regression test for relaying a maximum-sized failure and correct the existing size test to include the message type.
Reported by Project Loupe.
Co-Authored-By: Elias Rohrer <dev@tnull.de> Co-Authored-By: HAL 9000
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
fuzzing or regression evidencesecond-pass: broader security terminology
Security candidateReturn `Err`s` instead of panicking on oversized messagesby Matt Corallo · 08f12bc7 · Aug 4, 2026 · 3 filesMessage 85 · StrongTriage 15Details
Commit message · Matt Corallo
Return `Err`s` instead of panicking on oversized messages
While this code should remain unreachable as it likely indicates we're going to end up force-closing a channel due to being unable to communicate with a peer, we shouldn't bring down the whole process for it if we can avoid it.
Instead, at least return an `Err` so we can figure out what to do with it in `PeerManager`.
Co-Authored-By: Claude <noreply@anthropic.com>
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
Why it was queued
cryptography-sensitive path
Lower-priorityAvoid panicking when attempting to send an oversized messageby Matt Corallo · c5fdc3bf · Aug 4, 2026 · 1 fileMessage 85 · StrongTriage 0Details
Commit message · Matt Corallo
Avoid panicking when attempting to send an oversized message
While this code should remain unreachable as it likely indicates we're going to end up force-closing a channel due to being unable to communicate with a peer, we shouldn't bring down the whole process for it if we can avoid it.
Co-Authored-By: Claude <noreply@anthropic.com>
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
AI review queuedReject attempts to advance one-hop blinded forward pathsby Matt Corallo · 969a40cf · Aug 4, 2026 · 4 filesMessage 83 · StrongTriage 5Details
Commit message · Matt Corallo
Reject attempts to advance one-hop blinded forward paths
A malicious reply path can contain a single decryptable forward hop. Advancing that path removed its only hop, causing onion construction to panic when a handler attempted to respond.
Reject paths with fewer than two hops before attempting to advance them. The regression test exercises the untrusted response path and verifies that it returns an error without panicking.
Reported by Project Loupe.
Test written by: Elias Rohrer <dev@tnull.de>, which was Co-Authored-By: HAL 9000
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
fuzzing or regression evidencesecond-pass: broader security terminology
lightning-types: replace Zl/Zp separators in `PrintableString`
`PrintableString` replaces control (`Cc`), "other" (`C*`, including `Cf`), and unassigned codepoints with U+FFFD, but U+2028 LINE SEPARATOR (`Zl`) and U+2029 PARAGRAPH SEPARATOR (`Zp`) passed through verbatim: `char::is_control` is `Cc`-only and the generated tables in `unicode.rs` only cover the top-level `C` categories. Many terminals and log viewers render U+2028/U+2029 as hard line breaks, so a peer-controlled string (node alias, BOLT 12 description/issuer/ payer_note, `peer_msg`) could inject forged log lines that appear sanitised.
Extend `contrib/gen_unicode_general_category.py` to also emit a `Zl`/`Zp` separator predicate and regenerate `unicode.rs` from the same UnicodeData 17.0.0 the existing tables were built from, then filter on the new predicate in `PrintableString`. `Zs` is deliberately excluded as it contains U+0020 SPACE. Add a regression test mirroring the existing bidi-override test.
Found by a Loupe scan, tracked by the Bitcoin Security Council: https://github.com/bitcoin-security-council/findings/pull/180
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
Why it was queued
fuzzing or regression evidence
Lower-priorityApply the unfunded channel peer limit to all unaccepted channelsby Matt Corallo · 56a4ee43 · Aug 4, 2026 · 2 filesMessage 73 · AdequateTriage 0Details
Commit message · Matt Corallo
Apply the unfunded channel peer limit to all unaccepted channels
If a peer floods us with channel requests, we previously failed to enforce `MAX_UNFUNDED_CHANNEL_PEERS` as we considered the peer to have some channels once it has more than one request pending.
Instead, we have to make sure we reject such channels by looking at pending channels as well.
Co-Authored-By: Claude <noreply@anthropic.com>
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
AI review queuedAllow filtered block rescans at the current tipby Elias Rohrer · 686f9860 · Aug 4, 2026 · 3 filesMessage 88 · StrongTriage 0Details
Commit message · Elias Rohrer
Allow filtered block rescans at the current tip
A valid same-block replay through Listen could panic OutputSweeper and ChannelManager because both required every filtered_block_connected call to advance the chain.
Treat callbacks matching the current tip as rescans, process their additional transaction data, and skip the duplicate best-block update while retaining chain-order checks for new blocks.
Fixes #3920
Reported by Project Loupe
Co-Authored-By: HAL 9000
88/100 · StrongMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Links an issue, advisory, or supporting reference
Why it was queued
second-pass: broader security terminology
AI review queuedAvoid panic when reorged claims cannot mergeby Matt Corallo · f1dc8487 · Aug 4, 2026 · 2 filesMessage 78 · AdequateTriage 5Details
Commit message · Matt Corallo
Avoid panic when reorged claims cannot merge
Previously, a deep reorg could resurrect an HTLC package at a height where it was no longer mergeable with its surviving claim. This caused `OnchainTxHandler::blocks_disconnected` to panic on an assertion.
When merging fails, we now preserve the resurrected package in `locktimed_packages` so normal block processing registers and broadcasts it as an independent claim. Add a regression test covering the reorg and subsequent broadcast.
Thanks to Kyle W. Santiago for reporting this issue.
Co-authored-by: Elias Rohrer <dev@tnull.de>
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Why it was queued
fuzzing or regression evidencesecond-pass: broader security terminology
✓ Descriptive subject✓ Names a concrete action or component! No meaningful explanatory body
Why it was queued
seed or entropy pathsigning or wallet path
AI analysis · Informational 15/100
This commit simply updates the 'repository' web links in 15 package metadata files from GitHub to a self-hosted Forgejo instance. It does not change any program code, build logic, dependencies, or security behavior. There is no security issue here.
Lower-priorityAccount for message type prefix len in prevtx length enforcementby Wilmer Paulino · d29e1415 · Jul 31, 2026 · 1 fileMessage 73 · AdequateTriage 0Details
Commit message · Wilmer Paulino
Account for message type prefix len in prevtx length enforcement
Lightning wire messages have a maximum size of 65535 bytes, which already accounts for the required two-byte message type prefix. Our `TxAddInput::prevtx` length enforcement relied solely on the `serialized_length` of the message, which does not account for the prefix.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
Retransmit splice_locked for 0-conf channels missing tx_signatures
When a 0-conf channel successfully negotiates a 0-conf splice only for one peer and a disconnection happens prior to the other peer receiving `tx_signatures`, we'd previously fail to handle the inferred `splice_locked` upon reconnection via the `my_current_funding_locked_txid` TLV since the peer had not considered the splice fully negotiated yet. In this case, an explicit retransmission of `splice_locked` is required as per the BOLT-2 requirement:
> Each node: > - If option_zeroconf has been negotiated: > - SHOULD send splice_locked immediately after exchanging tx_signatures.
73/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
bolt12: add pay_for_bolt12_invoice for externally-sourced invoices
Adds a new pay_for_bolt12_invoice method that pays a BOLT 12 invoice without requiring it to have been requested through LDK. Unlike the existing send_payment_for_bolt12_invoice, this method:
- Does not verify that the invoice was previously requested by LDK. - Accepts a caller-supplied payment_id (no deduplication by invoice). - Supports an optional partial amount_msats for multi-payer MPP flows, where multiple senders each contribute a portion of the invoice total. The onion total_msat is always set to the full invoice amount so the recipient can validate the MPP payment correctly.
Also adds OptionalBolt12PaymentParams and Bolt12PaymentError, and deprecates send_payment_for_bolt12_invoice and manually_handle_bolt12_invoices in favour of the new flow.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Include to_self_delay size in DelayedPaymentOutput weight calculation
SpendableOutputDescriptor::create_spendable_outputs_psbt estimated the witness weight of a to_local (DelayedPaymentOutput) input using MAX_WITNESS_LENGTH, which assumes the maximum 4-byte OP_CSV push of to_self_delay in the redeemscript. The real push can be as small as 1 byte for small to_self_delays, causing the estimate to overshoot by up to 3 WU. If this overshoot occurred in addition to a short signature, the max-overshoot debug_assert in KeysManager::spend_spendable_outputs would fail.
Add DelayedPaymentOutput::max_witness_length, which computes the witness length from the descriptor's actual to_self_delay, and use it in place of the MAX_WITNESS_LENGTH constant. This produces a more accurate weight estimate so that the debug_assert in spend_spendable_outputs never fails.
This bug was discovered using Smite.
90/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Names security-relevant behavior explicitly
Why it was queued
signing boundarysigning or wallet path
AI analysis · Low 26/100
This commit fixes a small accounting bug in how the Lightning wallet estimates the size (and therefore transaction fee) of a special Bitcoin transaction that sweeps funds back to the user after a channel closes. The old code always assumed the largest possible 4-byte encoding of a delay value, even when the real value used only 1 byte. That could make the fee estimate slightly too high and, in rare cases with a short digital signature, trigger an internal debug-only assertion failure. The fix computes the exact size based on the actual delay value and adds a regression test. It is not a remote exploit and does not risk loss of funds.
AI review queuedCorrect docs on `ChannelSigner::get_per_commitment_point`by Matt Corallo · 5057809b · Jul 28, 2026 · 1 fileMessage 65 · AdequateTriage 12Details
Commit message · Matt Corallo
Correct docs on `ChannelSigner::get_per_commitment_point`
This was apparently missed in 1f7b24900d16c841d55fc83e0e2057e241d5e
65/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
Lower-priorityfuzz: allow empty-channel force close with in-flight paymentsby Joost Jager · dbb12502 · Jul 28, 2026 · 1 fileMessage 83 · StrongTriage 5Details
Commit message · Joost Jager
fuzz: allow empty-channel force close with in-flight payments
The chanmon harness can now force-close a target channel as long as that channel itself has no pending HTLCs, even when another channel still carries an in-flight payment. When an explicit close succeeds, mark pending payments that routed over the closed channel as allowed to fail.
This is the narrowest extension beyond globally HTLC-free closes. It covers a payment that crossed one hop before its next, still-empty channel is closed, without yet modeling force closes of channels that themselves contain HTLCs. Route-aware failure tracking limits the allowance to affected payments.
83/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Start pending payments at MustSucceed and require every tracked PaymentFailed to follow an observed failure source. Cover receiver rejection, corruption, local send failure, local inbound forwarding failures, and the receive-side CLTV buffer.
Local inbound failures are classified when forwarding leaves an inbound HTLC waiting for its removal revoke, before the failure can reach the payer. For relayed failures, use OutboundHTLCDetails::source to retain exact inbound channel and HTLC IDs with the payment hash. This prevents same-hash MPP parts from being mistaken for a local failure root.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Rename the send-state query and local variables to describe whether LDK still has pending work. Route the existing pending-payment registration through one helper without changing which sends are tracked.
Later payment invariants must apply consistently to direct, forwarded, and MPP sends. Centralizing this lifecycle decision keeps tracking changes from diverging between send helpers.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Carry each send's minimum final CLTV expiry into payment registration. Thread PaymentTracker through HTLC message delivery and separate PaymentFailed from ProbeFailed dispatch.
A later invariant commit uses this context to classify failure roots. Keeping the plumbing separate reduces its behavioral review even though the minimum expiry remains temporarily unread.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Keep each hop ChannelId beside its SCID and retain the complete set of paths while a payment is pending. This is mechanical preparation; the new fields are intentionally not interpreted yet.
SCIDs remain the route-building input, while explicit closes identify channels by ChannelId. Carrying both representations in one path model lets a later force-close allowance match affected payments without reconstructing routes or maintaining parallel bookkeeping.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
Build direct, forwarded, and MPP routes from a shared per-path hop description. Derive route fees and node metadata from that description, and increase the CLTV delta by 100 for each successive hop.
Later failure tracking needs to describe the exact route that was sent. Keeping route construction and bookkeeping on one representation prevents them from drifting and prepares the tracker to retain more per-hop failure context.
78/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification