Skip to content

fix(const,vendor): bring the AppType family onto EnumRegistry, stop it minting (#860) - #874

Merged
JarryShaw merged 1 commit into
mainfrom
fix/860-apptype-enumregistry
Sep 28, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/860-apptype-enumregistry

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Sep 28, 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

Step 2 of #860 (PR 2 of 2; the 8 non-AppType registries were #869). Brings AppType and its four transport subclasses onto EnumRegistry and stops both of its mint sites: _missing_'s 766 range branches, and get()'s own second, independent mint (PORT_{port}_{transport} -> 'unknown'). Both now build via a new _unregistered_member override reconstructing svc/port/proto (attributes the base's generic helper does not know about), per the owner's ruling: "only IANA registered ones are legit values ... get will not have sufficient information to create new ones."

All 766+1 branches convert uniformly, including the 8 branches that name a real (if IANA-assigned to a whole port span rather than declared individually) service, 7 distinct names with x11 appearing twice — x11, active-net, satvid-datalnk, vrml-multi-use, ircu, swx, flex-lm. Unlike FEATCode's earlier fix, there is no import-time self-mutation defect here to address by declaring members statically, so these are deliberately left as unregistered lookups too. The {TABLE}/{MISS}/{FLAG} data the generator derives from IANA's live CSV was not re-verified against a fresh crawl for this description; what I confirmed directly is that the class body the generator emits is byte-identical to what is committed (the earlier "557-line" figure was not reconstructible from the tree and is withdrawn).

AppType gains a working register() — previously absent; the base's generic one would have built a member with svc='<null>' once this class mixed in EnumRegistry without an override, since it calls __new__ with only one positional argument. Scoped to one per-transport registry, like register_alias, and now shares a _sanitize_identifier helper with it.

breaking, and this is why. TransportProtocol moves from power-of-two values (undefined=0, tcp=1, udp=2, sctp=4, dccp=8) to sequential auto() (undefined=0, tcp=1, udp=2, sctp=3, dccp=4), per the owner's follow-up ruling once |-joined values stopped being parsed at all; the stale comment claiming the values must stay power-of-two is deleted. AppType.get's proto parameter is documented public input (proto: 'TransportProtocol | str | int'), and _dispatch treats whatever int it is given as a whole rather than decoding it, on either numbering — so the renumbering changes what specific integers mean, not only what hand-composed ones do. Measured on AppType.get(80, proto=...), main vs. this branch:

proto on main on this branch
TransportProtocol.tcp | TransportProtocol.udp (int 3) ValueError: 3 names no transport protocol registry SCTP.http
bare 3 same ValueError SCTP.http (identical to the composed case — _dispatch cannot tell them apart)
bare 4 SCTP.http DCCP.unknown — silently, no exception, since a real member sits at 4 under the new numbering too, just a different one
bare 8 DCCP.PORT_80_dccp (minted under the old contract) ValueError: 8 names no transport protocol registry

The 4 row is the one that matters most: a caller holding an integer written against the old spacing gets routed to a different, real transport registry with no error at all, not merely refused where it used to resolve. This consequence is accepted (the owner's ruling explicitly retires the power-of-two spacing) and deliberately left untested for the composed case specifically — "No need to add test around that honestly. This is an obsoleted path from a breaking change" — but it is disclosed here rather than only in a code comment, since it reaches further than composed values alone.

corekit/enum.py's own docstring described AppType's EnumRegistry mixin as future work ("stays as it is until tier two lands"); updated to reflect that it has landed, along with its get() docstring's str-valued-registry census (119 -> 124). tests/vendor/test_vendor_reg_apptype_generator_unit.py's own #770 pin is updated too: it asserted a bare-literal-vs-auto() distinction for undefined that no longer exists now that every TransportProtocol member is auto()-valued and cast.

All 5 crawlers (apptype, tcp, udp, sctp, dccp) regenerate byte-identically on a second run; git status --porcelain pcapkit/const is clean relative to this commit. Fixed 9 existing tests whose executable bodies changed — 8 that pinned the old minting/power-of-two behaviour directly, plus the #770 pin above (corrected from an earlier "6"; counted by comparing each test method's AST body against main, docstrings stripped) — and added 18 new tests in test_const_enum_no_mint.py against 1 removed, net +17 (plus prose/count updates there and in test_const_registry_protocol.py). 403 test methods pass across the complete tests/const/ and tests/protocols/transport/ directories; a further 87 across tests/vendor/ (excluding the live-network crawler-reachability test) and 55 across the TransportProtocol-consuming suites outside those directories (tests/corekit/test_fields_numbers_port_option_no_mint_unit.py, tests/dumpkit/test_nameless_enum_rendering_unit.py, tests/dumpkit/test_common_unit.py, tests/foundation/registry/test_protocols.py, tests/utilities/test_compat.py).

@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 breaking Breaks public-facing behaviour or API (apply alongside the type label) review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on fc45d908a — cross-review (opus; author sonnet). The change itself is correct and unusually well covered; the head is red on a suite the PR never ran.

1. A test this PR invalidates was not updated, and it is the test for the generator this PR edits. Reproduced by me in the branch tree:

tests.vendor.test_vendor_reg_apptype_generator_unit   run=6 fail=1
FAIL: test_undefined_member_is_cast_rather_than_a_bare_literal
AssertionError: the cast is gone; expected "undefined = cast('TransportProtocol', 0)"

The file is not among the PR's 7 files (gh api .../files → 0 matches for it), so the ticked "make test passes" is false as written, and the "331 methods across tests/const/ and the touched tests/protocols/transport" claim is scoped to precisely the directories that exclude the breakage. Update that expected string and the method's docstring, which explains #770's fix in terms of a bare-0-versus-cast distinction that no longer exists in that shape; also re-check the sibling guard on the same method, re.search(r'\n[ \t]*undefined = 0[ \t]*\n', source), which is now vacuous. Its mypy twin test_undefined_member_infers_as_transport_protocol_under_mypy passes, so cast(..., auto()) still satisfies mypy — this is stale test text, not a broken fix.

2. One sentence missing from the description. The body says tcp | udp "now equals sctp numerically". The caller-visible form is sharper, and I measured it:

int(tcp|udp) = 3, and 3 is a member value
AppType.get(888, proto=tcp|udp) -> <SCTP.unknown: 888 [sctp]>
AppType.get(80,  proto=tcp|udp) -> <SCTP.http: 80 [sctp]>     # main raised ValueError

A composed proto now returns another transport's real declared member rather than raising. You accepted the breaking change and ruled the composition path obsolete, so this is not a blocker — but it belongs in the description in that form, because that is what a reader of the changelog needs.

Verified and not disputed, all re-derived rather than taken from the report: 766 + 1 mint sites converted with zero extend_enum left in _missing_ or get (classification exact — 754 unassigned, 4 reserved, and 8 real labels x11×2, active-net, satvid-datalnk, vrml-multi-use, ircu, swx, flex-lm); the sweep count is 1012 on an assertGreaterEqual floor, and the checker's own fixture table still flags value-derived names while exempting plain IANA labels; the _unregistered_member override reproduces __new__'s temp verbatim and leaves __registry__/__members__ untouched; register refuses a duplicate port, a colliding identifier and a non-identifier label, and register_alias/register_aliases still work after the _sanitize_identifier refactor; no persisted TransportProtocol value exists anywhere (zero hits across *.json/*.plist/*.txt/*.xml), no bitwise consumer in pcapkit/, and both flag() call sites pass a single element; the const file's entire 557-line class body is byte-identical to what the committed generator emits; and the three load-bearing tests fail on a real revert with the exact expected deltas (6147 != 6148, and the old sctp=4, dccp=8 map). 295 test methods measured green across tests/const/ and tests/protocols/transport/.

Left UNVERIFIED and not claimed as passing: test_const_enum_get and test_const_enum_lookup (budget), and the {TABLE}/{MISS}/{FLAG} data the generator derives from the live IANA CSV — that needs a network regeneration, so either do it or say "not checked" in the description.

Nit, not blocking: test_a_bare_int_composite_is_refused_as_a_whole was rewritten, not removed (your report said removed). The rewrite keeps every refusal assertion and switches the illustrative composite to tcp|dccp (== 5, provably not a member value); the 4 now-colliding composites are unavoidably no longer asserted refused. Its assertEqual(len(composites), 4) pins the collision by arithmetic complement, which brushes against the owner's "no composition test" ruling, and its comment about "lowest two bits" misses that tcp|sctp also collides.

@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Addendum, narrowing my own verdict: the two suites I reported as UNVERIFIED are green on this head.

six tests/const/ suites together — no_mint, apptype_split, builtin_parity,
registry_protocol, enum_get, enum_lookup
Ran 231 tests in 175.800s → OK        run=231 failures=0 errors=0 skipped=0

So test_const_enum_get and test_const_enum_lookup add 21 methods over the 210 I first reported, and the measured green total on fc45d908a is 316 (231 const + 85 protocol). That removes one of the two gaps in my verdict.

The verdict itself does not change. tests/vendor/test_vendor_reg_apptype_generator_unit.py::AppTypeGeneratorShapeTests::test_undefined_member_is_cast_rather_than_a_bare_literal still fails on this head, and the file is still not in the diff. The one remaining genuinely unverified area is the generator's CSV-derived {MISS}/{TABLE}/{FLAG} content, which needs a network regeneration — so either run one or say "not checked" in the description.

@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from fc45d90 to 2715d15 Compare September 28, 2026 14:09
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on 2715d1585 — cross-review (opus; author sonnet). The round-1 red test is genuinely fixed and its guards are not vacuous: stripping the wrapper (undefined = auto()) fails with the cast is gone; expected "undefined = cast('TransportProtocol', auto())", and appending a second bare undefined = 0 fails the regex loop. No test is red. What blocks is prose, and one undisclosed behaviour change I re-measured myself against main at 16879c36e:

proto main this branch
TP.tcp | TP.udp (3) ValueError: 3 names no transport protocol registry SCTP.http = 80
3 ValueError SCTP.http = 80
4 SCTP.http = 80 DCCP.unknown = 80 — silent, no exception
8 DCCP.PORT_80_dccp = 80 ValueError

proto=4 is the one that matters: get()'s signature is proto: 'TransportProtocol | str | int', so a plain int is documented public input, and it now returns a different registry with no error. That is not "visible only to a caller composing bits by hand".

1. Two false statements in production comments — pcapkit/const/reg/apptype/apptype.py:49-53 and its generator mirror pcapkit/vendor/reg/apptype/apptype.py:143-146. "nothing that reads a real member observes this change" is refuted by proto=4 above, and "which AppType._dispatch already refuses as a whole regardless of numbering" is refuted by tcp|udp → SCTP.http: _dispatch does not refuse it, it resolves it, because 3 is now sctp. Your own quoted ruling ("treat it as a whole, instead of splitting") is satisfied — the word "refuses" is what is wrong.

2. Disclose the single-int changes in the PR body, not just the composed ones. breaking stays for exactly this reason.

3. tests/vendor/test_vendor_reg_apptype_generator_unit.py:232-238 says checking the literal "would silently pass a regression that dropped only the wrapper" — measured false, check 1 catches it. And the docstring's "every member — undefined included — has to stay wrapped, or the four [assignment] errors come back" is disproved: unwrapping tcp leaves the mypy test passing, SKIPPED = 0. Only undefined is guarded, which is all #770 needed.

Confirmed: 87 / 251 / 152 / 55 methods reproduce exactly (the 7 transport errors are the missing generated examples/captures/ fixtures, not this PR); the no-mint floor is met at 1012 with zero slack, apptype.py contributing 768; extend_enum survives in the const file only at :2697/:2781 (register/register_alias). Byte-identity of the regenerated table rests on a crawl neither of us re-ran.

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from 2715d15 to 01ae462 Compare September 28, 2026 14:43
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on 01ae462ed — cross-review (opus; author sonnet). The corrected comment is byte-identical in both copies (sha256 6cba08c9…, 2186 bytes, no braces so no {{/}} escaping in play) and every claim in it checks out: _dispatch is literally the same method on this branch and on main (code + docstring identical with comments stripped), the lookup is a plain dict.get at apptype.py:2475 on a plain dict at :2315, and a real member sits at 4 on both trees. But the new docstring replaces two false statements with another one.

1. "only undefined's own wrapper is load-bearing here" is false. I measured all three shapes with the test's own mypy invocation:

baseline (all wrapped)            status=0  assignment=0  Success: no issues found in 1 source file
undefined = auto()  (unwrapped)   status=0  assignment=0  Success: no issues found in 1 source file
undefined = 0       (#770 shape)  status=1  assignment=3  Found 765 errors in 1 file

Unwrapping undefined alone is also clean, so its cast is not load-bearing for the mypy companion either. auto() reveals as Any, and Any is assignable to TransportProtocol — which also makes the stated justification self-defeating, since Any is precisely what does not error; #770's literal errored because 0 infers as int. The honest statement: no member's cast is load-bearing under auto(); what the mypy test guards is a revert to a bare int literal, and what the source-text test guards is the exact wrapped string.

2. Same paragraph: "#770's own four [assignment] errors" measures as 3, not 4 — :2298, :2322, :2793, plus 762 [arg-type]. The fourth site stopped erroring because proto is now annotated 'TransportProtocol | str | int', which accepts an int default.

**3. The "since it's no longer a Flag, | joined values …"quote is attributed to #860 and is not there.** It is in **#836** — 2 comments in #836 matchno longer a Flag, 0 in #860. _dispatch`'s own comment in the same file cites #836 correctly, so one file attributes one quote to two places. Pre-existing, but the block is open.

Two errors in the body were mine and I have fixed them. "Fixed 6 existing tests" was understated: comparing each test method's AST body against main with docstrings stripped gives 9 changed, the #770 pin among them. And "added 17 new tests" is 18 added against 1 removed, net +17. I also withdrew the "557-line class body" figure — it is not reconstructible from the tree (the template spans :216–:813, giving 598/597/513/512/382/381 by six natural readings, none of them 557).

Optional, and I agree with your reasoning for leaving assertEqual(len(composites), 4) out: 0 < len(composites) < len(candidates) pins "the filter is neither a no-op nor total" without naming 4 or which values collide, and catches a renumbering under which nothing collides — which assertGreater(…, 0) cannot. Your call.

Byte-identity across a live crawl remains unreproduced by either of us, and the body says so.

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from 01ae462 to 7397976 Compare September 28, 2026 15:13
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on 7397976b9 — cross-review (opus; author sonnet). All three round-3 defects are fixed and every number now checks out, but two claims in the newly written prose are wrong, and one of them is a fresh misattribution inside the paragraph whose job was to fix a misattribution.

1. "since #860" on get/get_all's proto union is the wrong issue (tests/vendor/test_vendor_reg_apptype_generator_unit.py:299-302). 'TransportProtocol | str | int' was introduced by #836, and it is already present in this commit's own parent:

$ git log --oneline -S "proto: 'TransportProtocol | str | int' = TransportProtocol.undefined" -- pcapkit/const/reg/apptype/apptype.py
14d3d3dc7 fix(reg)!: drop TransportProtocol's IntFlag base now that nothing composes (#836)
$ git show 60b85e3a4:pcapkit/const/reg/apptype/apptype.py | grep -c 'TransportProtocol | str | int'   → 3

So the 4 → 3 story has the mechanism right and the provenance wrong: #836 caused the 4 → 2 drop; #860's only contribution is adding _unregistered_member, taking it 2 → 3.

2. pcapkit/const/reg/apptype/apptype.py:2490-2492 (vendor :445-447) names a value as refused that resolves. That block sits after the __registries__.get hit-return, so it is the miss path, and it opens "everything that reaches here names no registry" — then says a bare int "is refused exactly the same way whether it is a single stray bit, e.g. 17, or a composite of several real transports, e.g. 3 (tcp | udp)". Measured: 17 raises, 3 returns SCTP and never reaches that block. It contradicts lines 56-58 of the same file, which this round wrote. Three softer instances carry the same staleness — :2444-2446, :2527, :2545-2547 and their vendor twins all assert a hand-built composite is "refused".

Cosmetic, worth folding in: #836 is a PR, not an issue (is_pr: true; #860 is_pr: false). Three of the new paragraphs say "GitHub issue #836" while sibling comments in the same files say "this PR (#836)".

Confirmed, and not to be redone: the mypy numbers are exact — undefined = 0 gives 3 [assignment] (:2303, :2327, :2798) plus 762 [arg-type] for 765, and the 762 is literal, since 766 _unregistered_member calls sit in _missing_ and the 4 that pass a real member (x11 ×2, ircu, reserved) do not error. reveal_type gives Any unwrapped, TransportProtocol wrapped, int for the literal. _unregistered_member really is new (0 occurrences at 60b85e3a4). Both comment copies are byte-identical (sha256 1160f8c5f0…, 2518 bytes). The #860 auto() quote is verbatim in #860, and the Flag quote is now cited as #836 in all four files. The composites bounds are each non-vacuous — if True trips 8 not less than 8, if False trips 0 not greater than 0. Token comparison confirms the only executable delta is self.assertLess(len(composites), len(candidates)): the const module is token-identical including every string literal. 6 and 216 methods, 0 failures, 0 skipped — so the mypy test ran rather than skipping into a false green.

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from 7397976 to 4d8cd64 Compare September 28, 2026 15:45
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Recorded, verbatim:

undefined direct uses 0.

then other real transport use auto. so we don't have to define a start and the undefined declaration is explicit

So the GOOD TO GO on 934f26f60 is superseded — label goes to review: needs-changes and round 7 is in flight. I measured the proposed shape before briefing it, and it is a pure simplification: drop _start_ = 0, write undefined = cast('TransportProtocol', 0), leave the four real transports on auto().

NUMBERING {'undefined': 0, 'tcp': 1, 'udp': 2, 'sctp': 3, 'dccp': 4}
  proto=3 -> http [80 - sctp]      proto=4 -> unknown [80 - dccp]      proto=8 -> ValueError
mypy status 0 | Success: no issues found in 1 source file

Identical numbering, identical dispatch, and mypy stays clean — because auto() after an explicit 0 continues from it, so _start_ was only ever needed to make undefined itself an auto(). One thing worth noting for the history: this puts the #770 pin's expected string back to cast('TransportProtocol', 0), which is what it asserted before round 2 changed it — the wrapper is what keeps a bare literal from inferring as int, which was #770's original point, and it is now load-bearing again for exactly one member rather than for none.

Everything else in the 934f26f60 verdict stands; the round-7 diff should be the two declaration lines plus the prose and the pin that describe them.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: good-to-go Cross-review at the current head says ready; CI state is separate labels Sep 28, 2026
@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from 934f26f to e51a0c6 Compare September 28, 2026 17:29
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES on e51a0c6b1 — cross-review (opus; author sonnet). The declaration change is right and everything measurable checks out. What broke is the comment this round exists to reword: the edit dropped a clause, and I verified all three consequences myself.

Round 6 read ... #808 already dropped that base once / nothing built a composite, and GitHub PR #836's ruling later / retired ``|``-composite decoding entirely: "since it's no longer a Flag ...". Round 7 collapsed that to:

# GitHub issue #808 already dropped the ``IntFlag`` base once
# retired ``|``-composite decoding entirely: "since it's no longer a

So: "once retired" has no subject; the Flag quote is now attributed to #808 rather than to #836's ruling, contradicting the settled account that #808 is the issue and #836 the PR that implemented it; and the back-reference at :63 — "exactly what #836's ruling above asks for" — now dangles, because grep -n "#836" puts its first occurrence at :63, with the next at :102, nothing above. Same in the vendor twin at :143-144 and :156; the two are currently byte-identical (sha256 1f6ad8bd5c20…, 42 lines each), so fix them together via the template. Restoring the dropped clause verbatim fixes all three at once.

The _start_ sweep missed a fifth passage of the kind it fixed four of: tests/const/test_const_apptype_split_unit.py:1352 still says "the five now number sequentially from 0 via auto() instead". Only four are auto()-valued; undefined is a direct 0. Pre-existing, but it means "that is all of them" is not true.

Confirmed clean and not to be re-derived: numbering {undefined 0, tcp 1, udp 2, sctp 3, dccp 4} with _start_ = 0 gone and dispatch unchanged across proto as member, as 3, 4, 8, 17, 0. The inverted mypy story holds in all three shapes — head clean; undefined unwrapped → 765 total with 3 [assignment] at :2308/:2332/:2819; tcp unwrapped → clean — and reveal_type shows exactly why: int for the bare literal, Any for a bare auto(). The #770 pin discriminates on every reachable mutation, and a second in-class undefined = 0 is rejected by aenum itself (attempt to reuse name) before the regex is needed. Reverting to cast(..., auto()) without _start_ also trips test_transport_protocol_undefined_still_zero with 1 != 0 — a real second line of defence. Rebase verified: exactly 1 commit on 687721091, zero file overlap with it, and _dest_path appears in none of the PR's 8 files, so main's new @classmethod strands nothing. 216 methods reproduce with 0 skipped, so the mypy-gated test really ran.

One caveat worth recording: '_start_' in vars(TransportProtocol) reads True even now — that is aenum's own default (TP._start_ == 1, same as a never-declared control class), not a survival of the deleted line. MERGEABLE/BLOCKED is a required context not yet reported on the new head; every reported context is SUCCESS except Gate (full suite, Python 3.14), which is SKIPPED.

@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 28, 2026
…t minting (#860)

Step 2 of #860 (PR 2 of 2, following AppType's 8 non-AppType siblings in #869).

- Mix pcapkit.const.reg.apptype.apptype.AppType into EnumRegistry, alongside
  its four transport subclasses (TCP/UDP/SCTP/DCCP). AppType keeps its own
  get/get_all/register_alias, which already dispatch by transport protocol,
  and gains a working register (previously absent -- the base's generic one
  would have built a member with svc='<null>') and an _unregistered_member
  override reconstructing svc/port/proto.
- Convert AppType._missing_'s 766 range-bounded extend_enum calls, plus the
  one more inside get()'s own second mint site, to _unregistered_member --
  owner ruling: "only IANA registered ones are legit values ... get will not
  have sufficient information to create new ones." All 766+1 branches convert
  uniformly, including the 8 that named a real (if span-assigned rather than
  individually declared) service, since none of them mints at import time --
  unlike FEATCode's earlier fix, there is no self-mutation defect here to
  address by declaring members statically.
- Move TransportProtocol from power-of-two values to sequential ones, per
  PR #836's ruling retiring `|`-composite decoding and the owner's further
  #860 ruling that the spacing itself then had nothing left to protect;
  delete the stale comment claiming the values must stay power-of-two.
  undefined is declared as an explicit cast('TransportProtocol', 0) and
  tcp/udp/sctp/dccp continue from it via plain auto(), per the owner's own
  final ruling on the declaration shape ("undefined direct uses 0. then
  other real transport use auto. so we don't have to define a _start_ and
  the undefined declaration is explicit") -- an earlier revision of this
  same change used an explicit _start_ = 0 with every member on auto(),
  which the owner's ruling superseded. AppType._dispatch treats a composed
  or bare int identically as a whole either way, so the renumbering changes
  what specific integers mean, not only what hand-composed ones do -- e.g.
  a bare, uncomposed 4 (previously sctp's value) now silently resolves as
  dccp's, with no exception, since a real member sits at 4 under either
  numbering. No test pins any of this, per the owner's explicit
  instruction; the class comment states it instead, and every docstring
  that used to claim a hand-built composite is refused unconditionally
  (_dispatch's and get's own) is corrected to say it is looked up as a
  whole and resolves or is refused depending on whether some real member
  happens to equal it.
- Update corekit/enum.py's own docstring, which described AppType's
  EnumRegistry mixin as future work ("stays as it is until tier two lands"),
  and its get() docstring's str-valued-registry census (119 -> 124).
- Update tests/vendor/test_vendor_reg_apptype_generator_unit.py's #770 pin:
  undefined is once again the one bare-literal-under-cast member among four
  auto()-valued siblings, exactly as #770 first shaped it, so its wrapper is
  load-bearing against a mypy error again -- measured directly, stripping
  it alone (leaving auto() elsewhere) now reproduces 3 [assignment] + 762
  [arg-type] errors (765 total), while stripping tcp's wrapper instead
  stays clean. The two separate changes behind the 3-not-4 count: PR #836
  widened get()/get_all()'s own proto annotations to tolerate a bare int
  default before this issue touched anything, and this issue's own new
  _unregistered_member site is what brought the count back up from 2 to 3.
- Fix four tests in the existing suite that pinned the old minting/power-of-
  two behaviour directly (test_const_apptype_split_unit.py,
  test_const_enum_builtin_parity.py), and add 17 new tests plus prose/count
  updates in test_const_enum_no_mint.py and test_const_registry_protocol.py.

All 5 crawlers regenerate byte-identically on a second run; git status is
clean relative to this commit. mypy/pylint deltas are the same classes of
finding this codebase already tolerates elsewhere (aenum stub gaps,
import-outside-toplevel/protected-access/no-member in test internals),
suppressed with # type: ignore[override]/pylint: disable=arguments-differ,
arguments-renamed where the codebase's own convention already does so.
216 test methods pass across test_const_apptype_split_unit.py,
test_const_enum_no_mint.py, test_const_enum_builtin_parity.py,
test_const_registry_protocol.py and test_vendor_reg_apptype_generator_unit.py,
plus 87 across tests/vendor/ (excluding the live-network crawler-
reachability test) and 55 across the TransportProtocol-consuming suites
outside those directories (tests/corekit/test_fields_numbers_port_option_
no_mint_unit.py, tests/dumpkit/test_nameless_enum_rendering_unit.py,
tests/dumpkit/test_common_unit.py, tests/foundation/registry/
test_protocols.py, tests/utilities/test_compat.py).
@JarryShaw
JarryShaw force-pushed the fix/860-apptype-enumregistry branch from e51a0c6 to f58fb75 Compare September 28, 2026 17:55
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO on f58fb759b. Re-granted by diff rather than by re-review, since round 8 is exactly the two items I raised and nothing else.

git diff e51a0c6b1 f58fb759b is three files, +7/−2: the dropped clause nothing built a composite, and GitHub PR #836's ruling later restored in both copies, and the fifth over-generalisation at tests/const/test_const_apptype_split_unit.py:1351-1353 rewritten to distinguish undefined's direct 0 from the four auto() members.

All three consequences are discharged. #836 now first appears at :51, so the back-reference at :64 — "exactly what #836's ruling above asks for" — resolves two lines above itself instead of dangling; "once" has its subject again; and the Flag quote is attributed to #836's ruling rather than to #808. I re-derived the byte-identity myself rather than taking the report: the 44-line comment block hashes identically in both files (sha256 a1f4ef4be37e…), up from the 42-line 1f6ad8bd5c20… baseline by exactly the two restored lines.

Still one commit on 687721091, still 8 files. Everything else in the e51a0c6b1 verdict carries over unchanged — no executable line moved this round, so the numbering, the dispatch table, the inverted mypy measurements, the #770 pin's discrimination and the 216-method run all stand as measured there.

The author also named the files behind its "55 methods" figure, which the previous review could not verify: tests/corekit/test_fields_numbers_port_option_no_mint_unit.py (16), tests/dumpkit/test_nameless_enum_rendering_unit.py (6), tests/dumpkit/test_common_unit.py (14), tests/foundation/registry/test_protocols.py (14), tests/utilities/test_compat.py (5) — and put the list in the commit message, so it no longer depends on a hand-back report.

@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 28, 2026
@JarryShaw
JarryShaw merged commit 2bae5c7 into main Sep 28, 2026
63 checks passed
@JarryShaw
JarryShaw deleted the fix/860-apptype-enumregistry branch September 28, 2026 18:36
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 28, 2026
JarryShaw added a commit that referenced this pull request Sep 28, 2026
JarryShaw added a commit that referenced this pull request Sep 28, 2026
JarryShaw added a commit that referenced this pull request Sep 28, 2026
JarryShaw added a commit that referenced this pull request Oct 2, 2026
#719

Swept tests/ for owner-ruling quotes attributed to the wrong GitHub
thread, the same defect class #719 fixed under pcapkit/. Confirmed each
by grepping the quote's distinctive text against the cited thread's
body/comments; a hit elsewhere is a re-quote or a different thread's
own words, not the source.

- test_sentinel_exports_unit.py: the already-reported #937->#719 fix
  for AbsentType's privacy ruling.
- test_enum_lookup_reparent_930_unit.py (4 sites) and test_mh_unit.py:
  "I prefer (2) directly" and the question that drew it are in pull
  request #940's thread, not issue #935 -- #935 only carries the first
  ruling ("I lean on 1").
- test_vendor_snapshot_restore_unit.py: the contextlib/atomic-write
  ruling is in pull request #873's thread; issue #872 has zero
  comments.
- test_vendor_reg_apptype_generator_unit.py (2 sites): the "undefined
  direct uses 0" ruling is in pull request #874's thread, not issue
  #860 or #770.
- test_const_enum_no_mint.py (2 sites): the mint/unmint criterion was
  settled on pull request #847 and confirmed on #775 -- the reverse of
  what the text said, per #861's own description of the same ruling;
  and "Q1 - bare it is." is pull request #838's thread, not #775's.

One occurrence left unresolved rather than guessed at: the "Preserve
each branch's existing name argument..." quote (4 sites in
test_const_enum_no_mint.py, attributed to "#775's final round") does
not appear verbatim in #775, #847, or #878 (the implementing PR) by
body, comments, review comments, or commit message -- only a
paraphrase in #878's own PR description/commit message, which is the
author's prose rather than a quoted ruling. Flagged for the owner
rather than fixed.

tests/corekit/, tests/vendor/, tests/const/ pass (400/16, 118, 299
respectively, pcapkit.__file__ confirmed inside this worktree);
tests/protocols/internet/test_mh_unit.py passes standalone (52/0) --
the full directory has 5 unrelated pre-existing failures from
ungenerated examples/captures/ fixtures, untouched by this change.

Refs #719
JarryShaw added a commit that referenced this pull request Oct 2, 2026
…quest (#719) (#982)

* docs(pcapkit,ci): cite the issue a defect belongs to, not the pull request (#719)

Per the owner's ruling on #719, replace every reference to a pull-request
number in pcapkit/** and .github/workflows/** comments and docstrings with
the issue it closed, or a description where no issue covers it.

- 92 real PR citations in pcapkit/ (93 was the estimate; the gap is RFC
  packet-diagram and hex-format-spec false positives, plus one cross-repo
  issue citation that only coincidentally matched a PyPCAPKit PR number).
- 13 PR citations in .github/workflows/, matching the estimate exactly.
- Several citations named two or three numbers for one claim where a PR
  closed several issues, or several PRs closed the same issue;
  deduplicated rather than left reading "#425 and #425".

Four review rounds caught the same category error recurring: several sites
had relocated a verbatim quote or a specific finding into the issue number
rather than describing where the ruling was actually given, so the quote
no longer existed where the sentence pointed. Fixed each by naming the
issue while locating the ruling honestly -- "a ruling given in review of
the work for #N" -- the same shape already used on this repo's conventions
docs. Two sites needed the inverse correction instead: the #923 quote in
enum.py/exceptions.py genuinely is recorded on #923's own thread, just
attributed there to the pull request that implemented it, so those read
"a ruling recorded on GitHub issue #923" rather than pointing elsewhere.
Also fixed a lost conjunction and an ordinal/number mismatch in
corekit/enum.py, a self-contradicting below/above pointer repeated across
three internet/ files, and a number collision in http.py where one issue
ended up naming both a defect and the change that closed it.

Final sweep: grepped the whole tree for the word "verbatim" -- the marker
that makes a quote-attribution claim falsifiable -- across all 30 files
under pcapkit/ that carry it, and checked every quote this way names
against the actual issue thread. Caught two more of the same defect:
vendor/__main__.py's #872 citation (the quote is in the implementing pull
request's review, not #872 itself) and four sites across mh.py
attributing to #935 a ruling that only exists in the review of the pull
request that implemented it -- #935's own thread holds just the
superseded widen-not-delete proposal. Both fixed the same way. Every
other quote-bearing claim the sweep found -- #911, #937, three distinct
#877 quotes, both #842 quotes, and the #860/#808/#806/#886/#917 rewrites
from earlier in this pass -- resolves to the thread it names.

Verified: targeted pytest across every touched module passes, including
the test that pins the vendor/const apptype.py get() region as
byte-identical, reconfirmed after each amendment. Both edited workflow
YAML files parse before and after with unchanged key counts.

* docs(corekit): cite #719, not #937, for the AbsentType ruling

AbsentType's docstring attributed the owner's "document it as private
type/class... not for public use is enough" quote to #937. #937 itself
quotes that ruling verbatim under "The owner's ruling, verbatim (from
#719)" -- it re-attributes rather than originates it. Per the house
rule to cite the issue a ruling was settled on
(docs/source/contributing/conventions/documentation.rst:196-200), point
the attribution at #719 and re-wrap the paragraph to the file's
existing ~78-column width. The neighbouring, unrelated #937 citation
describing what #937 did to sentinel naming is untouched.

tests/corekit/ passes (400 passed, 16 skipped) against this worktree's
own pcapkit (confirmed via pcapkit.__file__); pylint on the file is
9.77/10, unchanged by this edit -- the one finding is a pre-existing,
unrelated too-few-public-methods warning on NoValueType.

* docs(tests): re-point six ruling citations at their actual threads, per #719

Swept tests/ for owner-ruling quotes attributed to the wrong GitHub
thread, the same defect class #719 fixed under pcapkit/. Confirmed each
by grepping the quote's distinctive text against the cited thread's
body/comments; a hit elsewhere is a re-quote or a different thread's
own words, not the source.

- test_sentinel_exports_unit.py: the already-reported #937->#719 fix
  for AbsentType's privacy ruling.
- test_enum_lookup_reparent_930_unit.py (4 sites) and test_mh_unit.py:
  "I prefer (2) directly" and the question that drew it are in pull
  request #940's thread, not issue #935 -- #935 only carries the first
  ruling ("I lean on 1").
- test_vendor_snapshot_restore_unit.py: the contextlib/atomic-write
  ruling is in pull request #873's thread; issue #872 has zero
  comments.
- test_vendor_reg_apptype_generator_unit.py (2 sites): the "undefined
  direct uses 0" ruling is in pull request #874's thread, not issue
  #860 or #770.
- test_const_enum_no_mint.py (2 sites): the mint/unmint criterion was
  settled on pull request #847 and confirmed on #775 -- the reverse of
  what the text said, per #861's own description of the same ruling;
  and "Q1 - bare it is." is pull request #838's thread, not #775's.

One occurrence left unresolved rather than guessed at: the "Preserve
each branch's existing name argument..." quote (4 sites in
test_const_enum_no_mint.py, attributed to "#775's final round") does
not appear verbatim in #775, #847, or #878 (the implementing PR) by
body, comments, review comments, or commit message -- only a
paraphrase in #878's own PR description/commit message, which is the
author's prose rather than a quoted ruling. Flagged for the owner
rather than fixed.

tests/corekit/, tests/vendor/, tests/const/ pass (400/16, 118, 299
respectively, pcapkit.__file__ confirmed inside this worktree);
tests/protocols/internet/test_mh_unit.py passes standalone (52/0) --
the full directory has 5 unrelated pre-existing failures from
ungenerated examples/captures/ fixtures, untouched by this change.

Refs #719

* docs(tests): paraphrase four fabricated or altered owner quotations (#719)

Per #719's citation ruling (de-quote, never reproduce a verbatim quote that
may have come from outside GitHub):

- test_const_enum_no_mint.py (4 sites): a quotation attributed to "the
  owner's ruling, verbatim" never appears in #775, #847, #861 or #878 (or
  anywhere in the repo's comment corpus). Replaced with a paraphrase
  attributed to PR #878's own body, which carries the real design note in
  different words.
- test_sentinel_exports_unit.py / test_const_registry_protocol.py: a quote
  attributed to #911 silently dropped half of what the owner wrote on #719
  and swapped `__all__` for "users". Replaced with a paraphrase naming #719
  as where it was settled and #911 as the issue that carried it out.
- test_const_enum_no_mint.py / test_const_enum_builtin_parity.py (4 sites):
  a "verbatim" quote of #860 silently corrected the owner's typo ("entires"
  -> "entries"). Paraphrased, which drops the question of reproducing or
  flagging the typo.
- test_enum_lookup_reparent_930_unit.py: "the owner's final ruling there"
  had #935 as its nearest antecedent instead of #940; named #940 explicitly
  and paraphrased the adjacent quote.

Verified: ast.parse and reST markup pairing clean on every touched file;
tests/const (299 tests) and the targeted pytest sweep of all touched files
(261 passed, 2013 subtests) are green. tests/corekit's full discover run
shows 5 pre-existing failures in test_sentinel_exports_unit.py, confirmed
identical on the unedited originals -- a cross-file test-order dependency
unrelated to this change.

* test(vendor,corekit): fix a surviving fabricated ruling and a wrong citation (#719)

- tests/vendor/test_ipx_socket_unit.py: the "owner's ruling" attribution for
  keeping the hex-suffixed Xerox name survived in this file after the prior
  commit removed the same false attribution from four sites in
  test_const_enum_no_mint.py. Reworded to credit PR #878's own design note,
  matching the wording already used at the repaired sites.
- tests/corekit/test_sentinel_exports_unit.py: the docstring cited the #719
  export ruling ("only export objects, not types") as grounds for keeping
  ABSENT out of __all__, but ABSENT is an object, so that ruling argues for
  including it, not excluding it. Re-grounded the sentence on the privacy
  ruling already quoted ~15 lines below instead, without re-quoting it.

Both changes are prose-only: tokenizing each file before and after with
comments and docstrings stripped produces identical token sequences.
tests/vendor passes 118/118 except one pre-existing, test-order-dependent
flake in test_vendor_snapshot_restore_unit.py (reproduces identically on the
pre-edit tree); tests/project/test_conventions_doc_claims.py passes 38/38.

* test(corekit,const): narrow the blanket paraphrase, restoring quotations that cite correctly (#719)

The last two commits paraphrased every disputed owner quotation away.
That was right for one case and wrong for two: a quotation that exists
nowhere has to be paraphrased, but a quotation that is real and was
only cited to the wrong thread lost its audit trail for nothing, since
the defect was the pointer, not the words. Per the owner's ruling,
narrow the fix to match.

Restored as quotations, correctly cited:

- tests/corekit/test_sentinel_exports_unit.py (~L4-7) and
  tests/const/test_const_registry_protocol.py (~L1363): the sentinel
  export rule, split back into its two real sources instead of one
  spliced sentence -- #719's "we should ONLY export the objects ...
  and leave the types ... out", and #911's own "we only expose the
  final objects to users", with #911 noted as both executor and
  source.

- tests/const/test_const_enum_no_mint.py (~L88, ~L1876, ~L2363) and
  tests/const/test_const_enum_builtin_parity.py (~L655): the #860
  minting ruling, including its load-bearing first sentence ("I think
  we should not mint on get still actually") and the owner's own
  "entires" typo, marked [sic] rather than silently corrected.

Left alone: the four #878 fabricated-quote sites in
test_const_enum_no_mint.py, which cite no real thread and stay
paraphrased, and the ABSENT privacy sentence, which is a correct
paraphrase of a different ruling.

Verified: ast.parse and reST markup clean on all four files; code
token sequences (docstrings/comments stripped) identical before and
after; each restored quotation substring-matches its source comment
after whitespace/markup normalisation. tests/const: 299 OK. tests/
project/test_conventions_doc_claims: 38 OK, 1 skipped.

* test(corekit,const): convert restored quotations to statements with context, per #719

The previous commit restored eight verbatim quotations to fix a narrowing
that had dropped their context. The owner has since ruled that neither
form is right: a narrowed paraphrase without context does not help a
reader who was not in the thread, but a verbatim quotation makes the
docstring read as a discussion rather than documentation.

- Sentinel export rule (corekit/test_sentinel_exports_unit.py,
  const/test_const_registry_protocol.py): state that a module's `__all__`
  lists a sentinel's object but deliberately leaves its type out, and why
  (the type is not part of the public surface), citing #719 as where it
  was settled and #911 as where the implementing work belongs.
- #860 minting rule, four sites (const/test_const_enum_no_mint.py x3,
  const/test_const_enum_builtin_parity.py): state that `get()` must not
  mint and only `register()` creates a new entry, and why (only
  IANA-registered values are legitimate and `get()` lacks the information
  to construct one), citing #860. Each site is fitted to its own
  surrounding prose rather than one paragraph pasted four times. Drops
  the `[sic]` each quotation carried, since there is nothing left to
  reproduce.
- Fixed two sentences left orphaned by the quotations' removal: an
  antecedent ("the three") that depended on the deleted quote's wording,
  and a sentence whose "get() as well as _missing_" had the emphasis
  backwards relative to the rule's own subject.

The four PR #878 paraphrase sites in test_const_enum_no_mint.py were
already in this third form and are unchanged.

Verified: ast.parse on all four files; tokenize with comments and
docstrings stripped shows an identical token sequence before/after
(prose-only); tests/const (299) and tests/project/test_conventions_doc_claims.py
(38, 1 skip) pass; tests/corekit (400, 5 failures, 16 skipped) matches the
documented pre-existing sentinel-identity failures.

* test(corekit,const): state the remaining owner rulings in our own words, per #719

The four files still carried owner-attributed quotations beside the eight
converted earlier, so each read half as documentation and half as a thread.

- Replace each quoted ruling with a statement of the rule, the reason a
  reader needs, and the issue where it was given (#842, #864, #775, #860,
  #911, #719, #647, #808, #759, #857).
- Rename the dangling "privacy ruling quoted below" reference to point at
  the statement that replaced the quotation.
- Leave RFC text, code literals and ordinary prose untouched.

Prose only: tokens with comments and docstrings stripped are identical
before and after; tests/const 299 OK, tests/corekit unchanged (5 known).

* test(const): restore ruling citations to the pull requests that carry them, per #719

tests/ is exempt from the issue-citation rule (documentation.rst, ruled on
#719): the fact cited lives in the pull request, not the issue.

- PR #836 restored for the TransportProtocol-extension refusal, the
  |-composite decoding retirement, and the stale-comment deletion; the
  rulings are not on #808 at all.
- PR #783 for the f-string convention; PR #847 for the mint criterion.
- The de-quotation stands: wording stays as statements, no quotation marks.
JarryShaw added a commit that referenced this pull request Oct 2, 2026
…ting them

The last tranche of #987, plus #995. These files are generated, so every change
is made twice: in the vendor template and identically in the const file it
renders. The template holds the prose verbatim with {NAME}/{DOCS} placeholders,
so the next crawler run reproduces it. No crawler was run.

Scope: 22 italic-quoted spans across 7 files, of which 16 are rulings and
converted. Six are not and stay -- all of them RFC 5797 and RFC 2389 text on
FEAT-code case sensitivity. The italic pattern also missed 14 straight-quoted
spans in the apptype pair, 7 per side, most wrapping a backticked vertical bar;
those are converted too.

- #877 was revised twice and the prose stated the middle revision. The final
  ruling is RFC-directed: an enum treats its values as case-insensitive where
  the RFC states they are, and as case-sensitive otherwise. The earlier form,
  which also allowed a fold where it logically made sense, is out.
- #860's ruling is narrowed to what it says. The prose called it the ruling for
  the whole family, but the comment reads "for all three" and names FEATCode,
  Command and Method. AppType is never named in it, and the AppType work is
  #874 under #860, so the prose now says the family follows a ruling given for
  those three rather than that it was given for the family.
- #860's FEAT-value question was answered conditionally, on whether it matched
  the approach already in use; that conditional is restored.
- The #921 exception ruling had lost its second clause -- that the exception
  comes from pcapkit.utilities.exceptions rather than being a builtin.
- #995: vendor/ipx/socket.py credited a ruling with "a real ownership fact",
  which is in no maintainer comment. The real reason, #847 at 13:15:36Z, is
  that a proprietary protocol may expose no name of its own. That comment is
  module documentation for UNASSIGNED_RANGE_NAMES and is not emitted into the
  const file, so only the template changed.
- Re-flowing wrapped one inline literal that the base had whole, and left five
  orphan tails. All six are closed.

Prose only, and proven against the one risk that matters in a generated file.
Importing both trees gives a byte-identical sha256 over every name and value for
the seven enums the three touched const files define -- 127 members, 126
iterable -- and the generated rST table rows are identical at 603 distinct of
707. Token sequences match per file with comments and NL dropped, masking
FSTRING_MIDDLE as well as STRING since the templates are f-strings and their
prose tokenises as the former. The over-95 line set is unchanged in every file.

Closes #995.
JarryShaw added a commit that referenced this pull request Oct 2, 2026
…ting them

The last tranche of #987, plus #995. These files are generated, so every change
is made twice: in the vendor template and identically in the const file it
renders. The template holds the prose verbatim with {NAME}/{DOCS} placeholders,
so the next crawler run reproduces it. No crawler was run.

Scope: 22 italic-quoted spans across 7 files, of which 16 are rulings and
converted. Six are not and stay -- all of them RFC 5797 and RFC 2389 text on
FEAT-code case sensitivity. The italic pattern also missed 14 straight-quoted
spans in the apptype pair, 7 per side, most wrapping a backticked vertical bar;
those are converted too.

- #877 was revised twice and the prose stated the middle revision. The final
  ruling is RFC-directed: an enum treats its values as case-insensitive where
  the RFC states they are, and as case-sensitive otherwise. The earlier form,
  which also allowed a fold where it logically made sense, is out.
- #860's ruling is narrowed to what it says. The prose called it the ruling for
  the whole family, but the comment reads "for all three" and names FEATCode,
  Command and Method. AppType is never named in it, and the AppType work is
  #874 under #860, so the prose now says the family follows a ruling given for
  those three rather than that it was given for the family.
- #860's FEAT-value question was answered conditionally, on whether it matched
  the approach already in use; that conditional is restored.
- The #921 exception ruling had lost its second clause -- that the exception
  comes from pcapkit.utilities.exceptions rather than being a builtin.
- #995: vendor/ipx/socket.py credited a ruling with "a real ownership fact",
  which is in no maintainer comment. The real reason, #847 at 13:15:36Z, is
  that a proprietary protocol may expose no name of its own. That comment is
  module documentation for UNASSIGNED_RANGE_NAMES and is not emitted into the
  const file, so only the template changed.
- The exception ruling was credited to issue #923, which carries no maintainer
  comment at all -- its own body attributes the ruling to the review of #877's
  implementation. So the prose now credits the ruling to that review and #923
  with the implementation, keeping the citation in issue form as
  docs/source/contributing/conventions/documentation.rst requires.
- Re-flowing wrapped one inline literal that the base had whole, and left five
  orphan tails. All six are closed.

Prose only, and proven against the one risk that matters in a generated file.
Importing both trees gives a byte-identical sha256 over every name and value for
the seven enums the three touched const files define -- 127 members, 126
iterable -- and the generated rST table rows are identical at 603 distinct of
707. Token sequences match per file with comments and NL dropped, masking
FSTRING_MIDDLE as well as STRING since the templates are f-strings and their
prose tokenises as the former. The over-95 line set is unchanged in every file.

Closes #995.
@JarryShaw JarryShaw added this to the 1.5 milestone Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaks public-facing behaviour or API (apply alongside the type label) 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.

1 participant