Skip to content

fix(vendor): make the LinkType legacy-sink rule value-aware - #854

Merged
JarryShaw merged 1 commit into
mainfrom
fix/852-value-aware-legacy-sink
Sep 27, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/852-value-aware-legacy-sink

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Please follow the guide below

What is the purpose of your pull request?

  • fix — corrects a defect

Description of your pull request and other information

Closes #852 — the four follow-ups from #848's cross-review, plus two regressions this PR's own
cross-review found across two rounds. None was a live defect: a live fetch of
tcpdump.org/linktypes.html (205 rows) matches the old rule on exactly one row. These close the
ways it could go wrong later.

1. The predicate is now value-aware. #848 sank any row whose notes mentioned "legacy", never checking
whether the value was actually duplicated — so a future current row worded "supersedes the legacy DLT_FOO"
would have been sunk and recreated #844 in mirror image. process() now pre-scans data with a Counter
to build dup_values, computed independent of row order, and sinks only when
code_int in dup_values and 'legacy' in cmmt.lower().

Round 1 of that pre-scan only counted single-value rows (filtering the numeric column on
str.isdigit()), so a value duplicated across a range boundary — a single-value row sharing a value
with one member of a USER0-style range — was invisible to it, and that row's legacy alias stopped
being sunk: main-equivalent behaviour for such a pair emits ['USER0', ..., 'OLDUSER'] (current
canonical), the value-blind pre-scan emitted ['OLDUSER', 'USER0', ...] (legacy canonical, silently
wrong) — exactly the failure mode #844 and #852 exist to close, reopened by narrowing the predicate.
The pre-scan now expands a–b (en dash) ranges the same way the main loop does before counting, so a
range-boundary duplicate is no longer missed.

Round 2's fix still recognised a set of single values that was both narrower and wider than the main
loop's: str.isdigit() rejects a leading sign (+209, -5) and PEP 515 underscore grouping (2_09)
that the main loop's own int(temp) accepts, but it also accepts a Unicode decimal digit character
(e.g. '²⁰⁹'.isdigit() is True) that int() rejects — which on the previous head crashed the
pre-scan with an uncaught ValueError raised from inside the Counter generator expression itself,
before the main loop ever ran. The single-value branch now tries int(temp) directly, before the
en-dash check, so it recognises exactly what the main loop does in both directions — closing the
under-count for a signed/underscored value and the pre-scan-level crash for a Unicode-digit one at the
same time. Not reachable today (every one of the 220 committed members matches a plain unsigned
decimal), same as the range case above.

An ASCII hyphen is still never treated as a range, so a malformed numeric column (900-903,
900–903–905, an empty string) keeps raising loudly — in the main loop, at
start, stop = map(int, temp.split('–')), the same statement as before this PR. The pre-scan's own
_expand swallows every one of those forms and contributes no counted values for the row; it does not
itself raise, and does not change where the real raise happens.

2. The range branch no longer routes through sink. USER0–USER15 (147–162) append straight to enum
unconditionally, so one range row worded "legacy" can no longer move all sixteen expanded members at once.
Unaffected by the range-aware pre-scan above: dup_values is only consulted in the single-value branch.

3. The comment now describes what the code tests. The old one claimed a value-sharing check the predicate
never performed; it now documents value-duplication plus wording, at both the dup_values computation and
the sink = line, and documents the range-expansion and signed/underscored recognition the pre-scan does
before counting.

4. The out-of-order member is explained in the generated file (const/reg/linktype.py), so a reader
who finds IPMB_LINUX = 209 after DECT_NR_TAP = 304 sees why. That note is emitted as a plain # comment
rather than #: — a #: line immediately above an attribute becomes that attribute's rendered Sphinx
docstring, and this note is about the generator's own source layout, not about what IPMB_LINUX means to a
caller. It also names the fully-qualified pcapkit.vendor.reg.linktype.LinkType.process rather than the
bare LinkType.process, which is ambiguous with the const class of the same name.

Also fixed: the order-independence test previously proved nothing beyond what the 209 fixture already
covered — mutating the pre-scan into a prefix-only, order-dependent variant left it passing, because that
variant is only wrong for the first occurrence of a value it has not seen yet. It now drives the same
duplicate pair through process() in both orders itself, so the property is earned by the test named for it
rather than borrowed from LinkTypeGeneratorLegacyOrderingTests's separate 209 fixture. Also: the main
loop's code_int (already parsed by int(temp)) is now reused at the sink = line instead of re-parsing
code a second time.

Verification, re-run by me on the current head, freshly regenerated

LinkType(209).name        = I2C_LINUX
IPMB_LINUX is I2C_LINUX   = True   (both value 209)
members / iteration       = 220 / 219        (unchanged)
duplicated values         = {209: 2}         (still the only one)
USER0..USER15 values      = 147..162         (still contiguous)
  • Four tests are the point of this PR, and each genuinely fails against the code it targets. Against
    the value-blind, word-only predicate (fix(reg): emit tcpdump legacy link-type names after current ones #848 as merged, f990f2149), with the current 11-test file:
    2 failed, 9 passed — test_non_duplicated_legacy_wording_does_not_reorder and
    test_legacy_worded_range_row_still_lands_entirely_in_enum. Against round 1's range-blind pre-scan:
    test_legacy_row_duplicating_a_range_member_is_sunk fails, emitting
    ['OLDUSER', 'USER0', 'USER1', 'USER2', 'USER3'] instead of ['USER0', 'USER1', 'USER2', 'USER3', 'OLDUSER']. Against round 2's str.isdigit()-gated pre-scan:
    test_signed_value_pair_resolves_to_the_current_member and
    test_underscored_value_pair_resolves_to_the_current_member both fail, emitting ['OLD', 'CUR']
    instead of ['CUR', 'OLD']. On this head: 11 passed (Ran 11 tests … OK under plain unittest).
  • coverage run -m pytest tests/const tests/vendor → 196 passed, 39647 subtests passed
  • tests/test_tier_guard.py → 102 passed, 553 subtests — no new dependency gate; the file continues to
    guard on the existing HAS_VENDOR_DEPS
  • Every pre-scan widening is provably free of output churn. 147–162 each appear exactly once in the
    live table and no member is spelled with a sign, an underscore, or a Unicode digit, so dup_values
    stays {209} throughout — the range-aware, then the signed/underscored-aware, pre-scan change nothing
    about which rows get sunk. Isolated from the item-4 docstring-comment rewording (the only other
    change to the generated file), this head's committed const file with exactly its four new plain-#
    comment lines removed is byte-identical to merged main's: git cat-file blob origin/main:pcapkit/const/reg/linktype.py | md5sum and this head's blob with those four lines
    stripped both give md5 8210ae8084b10a8ea1e5f14c9266b35a, and a direct diff between the two is
    empty. (A stronger result than the all-comment-stripped d5d673b7324b9cd14f4eb1a8d0b5aa43 posted
    earlier on this PR: removing only the four new lines already reproduces main exactly, with no need
    to strip every # line to get there — which is what "not breaking" below actually rests on.) With
    the four comment lines included, the full const file regenerates reproducibly at md5
    9bf2f4b49c394df180beb4eff51d562f — confirmed to be exactly those four lines' worth of diff from
    merged main, nothing else.

One limitation stated rather than papered over

A wording-only signal still cannot save a genuine duplicate pair if tcpdump attaches "legacy" to the wrong
member of that pair. dup_values narrows the rule to real duplicates — including, now, duplicates that span a
range boundary or are spelled with a sign or an underscore — but if upstream ever words the current row of
a true pair as the legacy one, no amount of value-awareness detects it: the only signal available is the
prose. That residual is documented in the generator's comment rather than left implicit.

Three more, all pre-existing or deliberate, none introduced here and none needing a code change:
emission, not recognition, is the weak link for a non-ASCII decimal-digit row (e.g. Arabic-Indic
digits) — int() accepts such digits and recognises the value correctly, but code = temp reuses the
raw text verbatim in the emitted NAME = code literal, and Python source numeric literals are
ASCII-only, so the generated file would still raise a SyntaxError on import; pre-existing (code = temp predates this PR) and unreachable today, since every live row's number column is a plain ASCII
decimal. A legacy range row still cannot be sunk, since ranges never route through sink at all —
deliberate, item 2 of #852. And _expand materialises list(range(...)) where the main loop is lazy,
so a corrupt huge range would MemoryError in the pre-scan rather than hang — hypothetical either way,
and no more or less true of one branch than the other.

Not breaking: LinkType(209).name is I2C_LINUX before and after, no name disappears, no value
changes — and, per the byte-identity result above, the only change to the committed const file at all
is the four-line comment.

@JarryShaw JarryShaw added fix Pull requests that fix a defect (fix: subject prefix) const Regenerated IANA or vendor constant tables; members keep their numeric values review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on a302c96a7 — cross-review (opus, a different model from the sonnet author). One
required change, and it is a regression versus merged main, not an uncovered gap. I reproduced it myself
before relaying.

dup_values cannot see range-expanded values, so a value duplicated across a range boundary is not
recognised as duplicated — and its legacy row is no longer sunk.
The Counter comprehension filters on
temp.isdigit(), so '900–903' never enters it.

Two-row table: a single-value row 900 whose notes read "Legacy name (do not use) for the range below.",
followed by a range row 900–903. Fed straight through process() on both trees, pcapkit.__file__ asserted:

main (f990f2149)   emitted: ['USER0','USER1','USER2','USER3','OLDUSER']   canonical for 900 -> USER0   ✅
PR head a302c96a7  emitted: ['OLDUSER','USER0','USER1','USER2','USER3']   canonical for 900 -> OLDUSER  ❌

LinkType(900).name would return the deprecated name. No exception, no warning — the silent-wrong mode this
whole issue exists to close, reopened for a case #848's word-only rule happened to get right. The generator's
comment states the mechanism ("range rows … never consulted here") but does not warn that it reopens #844 for
an overlapping value, and the PR's "One limitation stated rather than papered over" names only the
wrong-member-wording residual. So there is a second, unstated residual that this diff introduces.

The fix is provably free, which is the part that settles it: patching the pre-scan to expand a–b before
counting leaves the regenerated const file byte-identical — md5 still 7f4db8d612d74fbdbc880f75040bff12,
git status clean — because each of 147–162 appears exactly once today, so dup_values stays {209}. Item 2
is unaffected, since dup_values is consulted only in the single-value branch. Add a test for that shape;
it fails on this head and passes with the expansion.

Everything else confirmed, several beyond what I had checked:

  • Item 4 is safe, and it was the case I flagged hardest. legacy[0] is guarded by if legacy:, so the
    expected future state — no legacy-worded duplicate — returns normally with no stray comment and no
    IndexError.
  • breaking correctly absent, established more tightly than the PR claimed: every NAME = value line
    extracted from both const files and diffed — identical in names, values and order, 220 lines; the const
    diff is +3/−0, comment only.
  • Malformed numeric columns still raise loudly, and now earlier — in the pre-scan, before any row is
    emitted — which is strictly better than main.
  • Three-row and neither-worded duplicate cases all resolve correctly.

One claim disputed as attributed: order-independence holds, but
test_duplicate_pair_canonical_member_is_order_independent is vacuous for it — mutating the pre-scan into
a prefix-only variant leaves that test passing, while LinkTypeGeneratorLegacyOrderingTests's 209 fixture
fails. The property is guarded, by the other class. Re-point the docstring and the PR's "independent of row
order" sentence, or make the test run one fixture in both orders so the name is earned.

Also worth fixing while in there: the three new #: lines land in LinkType.IPMB_LINUX's rendered Sphinx
docstring, and they reference LinkType.process, which does not exist on the const class — name
pcapkit.vendor.reg.linktype.LinkType explicitly. The 4 mypy errors on that file all git blame to 2019/2022
and are pre-existing.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
@JarryShaw
JarryShaw force-pushed the fix/852-value-aware-legacy-sink branch from a302c96 to f8b13b3 Compare September 27, 2026 15:05
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on f8b13b34f — second cross-review (opus, a different model from the sonnet author). The
code is sound; the cross-range regression is confirmed fixed. Three small changes, two of them prose. The worker
is on all three.

1. One genuine hole, and it is the same class of defect this PR exists to close. _expand's recognition set
(str.isdigit(), or an en-dash range) is narrower than the main loop's acceptance set (int(), which
accepts a leading sign and PEP 515 underscores). A value the main loop accepts but _expand does not is
invisible to dup_values, so its legacy alias silently stops being sunk — a regression versus merged main,
which got these right via the word-only rule. Reproduced by me on this head, pcapkit.__file__ asserted under a
detached worktree:

legacy '+209' + current '+209' -> ['OLD', 'CUR']   legacy canonical, WRONG
legacy  '209' + current  '209' -> ['CUR', 'OLD']   right

Same for -5 and 2_09. Not reachable today — all 220 committed members match ^\s{4}NAME = \d+$ — but it
makes the body's "so no overlap case is missed" an overstatement. Fix is one line: try: return [int(temp)] in
place of the isdigit() test, plus a test that fails without it.

2. A false clause in the PR description. It claims a malformed numeric column now raises "earlier — now
inside the pre-scan too, before the main loop reaches the same row"
. Nothing raises in the pre-scan —
_expand swallows every malformed form. Measured on this head: 9xx, 900-903, 900–903–905 and '' all
raise ValueError at pcapkit/vendor/reg/linktype.py:142, the main loop's start, stop = map(int, temp.split('–')) — the same statement on all three trees. It also contradicts this PR's own test docstring,
which correctly says the pre-scan swallows that ValueError.

3. test_malformed_en_dash_range_still_raises_loudly's docstring opens "must fail as quietly as it can, not
as loudly"
— inverted against its own name. And "2 failed, 5 passed" is stale: 2 failed / 7 passed now the
file has 9 tests.

Two of my own framings were refuted, both in this PR's favour, and I re-measured both before relaying:

  • I flagged _expand's except ValueError as regressing the "malformed columns raise loudly, and earlier, in
    the pre-scan" property the previous round praised. That property was never true. The pre-scan on
    a302c96a7 was int(temp) if temp.isdigit(), which filtered malformed values rather than raising on them.
    Twelve numeric-column forms measured across all three trees: the raise site is identical on every one.
  • I suspected an ASCII-hyphen range would leave the fix half-closed. It cannot produce a wrong name — it
    crashes: int('900-903') fails, the en-dash split yields one element, and start, stop = … raises. Same
    for em dash and U+2212. The author's claim was right.

Confirmed: the regression is fixed (head emits ['USER0','USER1','USER2','USER3','OLDUSER'], matching main,
where a302c96a7 emitted OLDUSER first); test_legacy_row_duplicating_a_range_member_is_sunk fails on the
previous head and passes here; the rewritten order-independence test earns its name by mutation — an
order-dependent pre-scan variant now fails it, where the old version passed; and dup_values is {209} with
USER0..USER15 contiguous at 147–162.

breaking correctly absent, established by me rather than taken on trust: const md5 9bf2f4b49c… (head) vs
8210ae8084… (main), but with all # lines stripped both are d5d673b7324b9cd14f4eb1a8d0b5aa43 — byte
identical. 220 members, no name, value or ordering change.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
Follow-ups from the cross-review of #848's legacy-sink rule in
pcapkit/vendor/reg/linktype.py:

- The sink predicate tested a row's notes for the word "legacy" alone,
  with no check that the row's value was actually claimed by another
  row -- so a future current row whose notes coincidentally mention
  "legacy" would be wrongly sunk. Gate the sink on the row's value
  being a genuine duplicate elsewhere in the table (pre-scanned via a
  Counter), computed independent of row order.
- The range branch (USER0-USER15) reused the same per-row sink, so one
  range row worded "legacy" would sink all sixteen expanded members at
  once. Range rows now always land in enum, unconditionally.
- Reworded the generator comment so it matches what the predicate
  actually tests, not "shares its value" when it never checked that.
- Added a comment at the const file's emission site, as a plain `#`
  line rather than `#:`, so it explains the source layout without
  leaking into IPMB_LINUX's rendered Sphinx docstring; qualified the
  self-reference as pcapkit.vendor.reg.linktype.LinkType.process.

Two rounds of cross-review on this fix itself then each caught a
narrower-than-main-loop hole in the duplicate-value pre-scan:

- Round 1: the pre-scan counted only single-value rows, so a value
  duplicated across a range boundary (a single-value row sharing a
  value with one member of a USER0-style range) was invisible to it.
  The pre-scan now expands en-dash ranges the same way the main loop
  does before counting.
- Round 2: the pre-scan's single-value branch tested str.isdigit(),
  narrower than the main loop's int(temp), which also accepts a
  leading sign and PEP 515 underscores. The pre-scan now tries
  int(temp) directly, before the en-dash check, so it recognises
  exactly what the main loop does. Neither hole is a live defect --
  every one of the 220 committed members matches a plain unsigned
  decimal -- but each was the same class of silent under-count this
  fix exists to close for ranges, narrowed further.

Also fixed: the order-independence test previously proved nothing
beyond what the 209 fixture already covered (mutating the pre-scan
into a prefix-only, order-dependent variant left it passing); it now
runs the same duplicate pair through process() in both orders itself.
And code_int (already parsed by int(temp)) is now reused at the
sink = line instead of re-parsing code a second time.

Added tests for: a non-duplicated value never sunk regardless of
wording, a duplicate pair resolving correctly in either table order,
range-sink isolation, the cross-range duplicate regression, a
malformed en-dash range still raising loudly in the main loop (not
the pre-scan), and signed/underscored duplicate pairs -- each shown
failing against the relevant prior code. Regenerated
pcapkit/const/reg/linktype.py at every round; each pre-scan widening
alone is byte-identical (md5 7f4db8d612d74fbdbc880f75040bff12) to the
prior fix, confirmed by isolating it from the docstring-comment
change, which is the only other diff. Invariants hold:
LinkType(209).name == 'I2C_LINUX', IPMB_LINUX and I2C_LINUX both alias
value 209, 220 members / 219 canonical iteration, 209 the only
duplicated value, USER0-USER15 still 147-162. tests/const + tests/vendor:
196 passed; tests/test_tier_guard.py: 102 passed (unittest-confirmed).
@JarryShaw
JarryShaw force-pushed the fix/852-value-aware-legacy-sink branch from f8b13b3 to bb20fe8 Compare September 27, 2026 15:34
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on bb20fe896 — third cross-review (opus). One line, prose only. The code is sound and every
code claim held.

The md5 at body line 100 is wrong. It cites 7f4db8d612d74fbdbc880f75040bff12 as the isolated,
comment-stripped regeneration output, "same as before this PR". Before this PR is merged main
(f990f2149), and that is 8210ae8084b10a8ea1e5f14c9266b35a. Measured by me three ways, all agreeing:

git cat-file blob origin/main:pcapkit/const/reg/linktype.py | md5sum
  -> 8210ae8084b10a8ea1e5f14c9266b35a
head, minus exactly the four new plain-# comment lines
  -> 8210ae8084b10a8ea1e5f14c9266b35a      identical

The claim itself is true — comment-stripped, the head's const file is byte-identical to main's. Only the
hash is unreproducible. This is the fourth false number in that body, in the paragraph whose entire purpose is
to be checkable, so it gets fixed rather than shrugged at.

Note this is a stronger result than the d5d673b7324b9cd14f4eb1a8d0b5aa43 figure I posted earlier: removing
only the four new lines already reproduces main exactly, so no all-comment stripping is needed to establish
byte-identity. breaking correctly absent stands, established more tightly than before.

The valuable new finding: str.isdigit() was wider than int() too, and nobody had noticed.
'²⁰⁹'.isdigit() is True but int('²⁰⁹') raises — verified directly. On f8b13b34f that made _expand raise
an uncaught ValueError from inside the Counter genexp (linktype.py:102 → :105 → :93). So the round-2 fix
closed a mismatch in both directions, and it is what makes the body's "the pre-scan does not itself raise"
true — that sentence would have been false on the previous head.

Completeness confirmed structurally and empirically. _expand:104 is return [int(temp)], the identical
expression
the main loop guards on at :132, applied to the identical string; both range branches are
map(int, temp.split('–')) then range(start, stop+1). Driven through the real process(): 209, +209, -5,
2_09, 2_0_9, +2_09, ' 209 ', '209\n', ٢٠٩, 123 all sink correctly; 0x00d1, 209.0, inf,
209_, –209 all raise loudly out of process(). No value either side accepts is missed by the other. The
reorder is safe because no string containing U+2013 can satisfy int().

Also confirmed: the two new tests fail on f8b13b34f with exactly ['OLD','CUR'] and only those two of eleven;
Ran 11 tests … OK here; a live regeneration against tcpdump.org reproduces the committed blob
byte-for-byte
(git status --porcelain empty, md5 9bf2f4b49c…); and int(code) ≡ code_int identically, with
sink now bound and read only inside the try, so no stale value can survive a row.

Three residuals recorded, none blocking and none introduced here: a unicode-digit row would emit
OLD = ٢٠٩, a SyntaxError, because Python literals are ASCII-only — pre-existing, and the weak link is
emission, not recognition; a legacy range row still cannot be sunk (deliberate, item 2 of #852); and
_expand materialises list(range(...)) where the main loop is lazy.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO on bb20fe896 — the single required change from the third cross-review is done, with no code
change and no new commit
, so the verdict that the code is sound carries forward to this exact sha.

The wrong md5 is corrected and re-derived rather than pasted. Verified independently by me:

git cat-file blob origin/main:pcapkit/const/reg/linktype.py | md5sum
  -> 8210ae8084b10a8ea1e5f14c9266b35a
head bb20fe896's const, minus exactly its four new plain-# comment lines (746-749)
  -> 8210ae8084b10a8ea1e5f14c9266b35a      and a direct diff against main's blob is EMPTY

Byte-identity, not a hash coincidence. breaking correctly absent now rests on that, which is tighter than
the all-comment-stripped d5d673b7324b9cd14f4eb1a8d0b5aa43 figure I posted earlier.

The body also now records what the third review found and neither the author nor I had spotted: str.isdigit()
was wider than int() as well as narrower.
'²⁰⁹'.isdigit() is True while int('²⁰⁹') raises, which on
f8b13b34f produced an uncaught ValueError from inside the Counter genexp. So the int(temp)-first
rewrite closed the mismatch in both directions, not just the signed/underscored one — and that is what makes
the body's "the pre-scan does not itself raise" sentence true rather than aspirational.

Three residuals recorded in the body, none fixed here and none introduced by this PR: a unicode-digit row would
emit OLD = ٢٠٩ and hence a SyntaxError, since Python numeric literals are ASCII-only (pre-existing, and the
weak link is emission, not recognition); a legacy range row still cannot be sunk (deliberate, item 2 of #852);
and _expand materialises list(range(...)) where the main loop is lazy.

CI on this head: 58 CheckRuns pass, 0 fail, 0 incomplete. Three rounds of cross-review, all on opus against a
sonnet author. Ready for you to merge — and note it is BEHIND current main under the strict policy, so it may
need updating before the button is available.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 27, 2026
@JarryShaw
JarryShaw merged commit 2578d52 into main Sep 27, 2026
62 checks passed
@JarryShaw
JarryShaw deleted the fix/852-value-aware-legacy-sink branch September 27, 2026 16:03
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 27, 2026
@JarryShaw JarryShaw added this to the 1.5 milestone Oct 6, 2026
@JarryShaw JarryShaw moved this to Done in PyPCAPKit Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

const Regenerated IANA or vendor constant tables; members keep their numeric values fix Pull requests that fix a defect (fix: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(vendor): make the LinkType legacy-sink rule value-aware, and correct its comment

1 participant