Skip to content

fix(scripts): gen_parity_gaps reads split api-manifest entries - #6504

Merged
proggeramlug merged 2 commits into
mainfrom
fix/gen-parity-gaps-manifest-path
Jul 17, 2026
Merged

fix(scripts): gen_parity_gaps reads split api-manifest entries#6504
proggeramlug merged 2 commits into
mainfrom
fix/gen-parity-gaps-manifest-path

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Root cause

scripts/gen_parity_gaps.py:35 hardcoded the manifest path to a single
file:

MANIFEST = ROOT / "crates" / "perry-api-manifest" / "src" / "entries.rs"

crates/perry-api-manifest/src/entries.rs was split into
entries/part_1.rs..part_4.rs on 2026-07-03 (5212 lines total, to stay
under the 2000-line CI gate). entries.rs (crates/perry-api-manifest/src/entries.rs:459-467)
now just declares mod part_1;..mod part_4; and concatenates them into
API_MANIFEST at compile time — the actual method(...)/property(...)
rows all moved into the split files. The script never picked up the split,
so parse_manifest() (scripts/gen_parity_gaps.py:122-126, old) parsed
entries.rs alone and found ~0 manifest rows, making almost every module
look unimplemented.

Before this fix, a dry run landed at 1753 covered / 765 gap (vs. the
true ballpark of ~2238/280) — e.g. node:os swung from 0 gaps to 143.

Fix

  • scripts/gen_parity_gaps.py: replaced the single MANIFEST path with
    MANIFEST_FILES = glob("entries*.rs") + glob("entries/*.rs"), and
    parse_manifest() now reads every matched file. Added a loud failure if
    zero manifest files are found, and a second loud failure if the total
    parsed entry count is implausibly low (< 1500), so a future re-split
    can't silently zero out most of the manifest again — the script exits
    with a clear message instead of quietly emitting bogus, worse-than-useless
    gap counts.
  • docs/runtime-parity-gaps.md: landed the 2026-07-16 hand-audited counts
    (2238 covered / 280 gap) that a prior audit session had already worked
    out but left uncommitted, and rewrote the banner + audit note to reflect
    the fixed script's actual dry-run output rather than the pre-fix
    catastrophic numbers.

Dry-run before / after

State Covered Gap node:os gap
Broken (single-file entries.rs path) 1753 765 143
Fixed (globs entries.rs + entries/*.rs) 2232 286 0
Hand-audited doc (2026-07-16) 2238 280 0

Spot-check of the 5 named items

Checked with python3 scripts/gen_parity_gaps.py --module <mod> after the
fix:

  • new AsyncLocalStorage() (node:async_hooks) — still listed as a gap
  • new URLSearchParams(...) overloads (node:url) — still listed as a
    gap
    ; params.entries()/.keys()/.values() on the same module are
    now recovered as covered
  • Buffer.allocUnsafeSlow (node:buffer) — still listed as a gap
  • stats.dev/.ino/.nlink/.rdev/.size/.blksize (node:fs) —
    still listed as a gap
  • new Worker(filename) (node:worker_threads) — still listed as a gap

So per the task's own fallback criterion, I did not run --emit /
regenerate the doc from scratch — the fixed script's manifest data still
wrongly lists 13 of the 16 hand-confirmed 2026-07-16 false positives as
missing, so a fresh --emit today would still be worse than the existing
hand-corrected file (2232/286 vs. 2238/280) and would silently drop the
hand-corrections. I only fixed the manifest-file-discovery bug, hand-landed
the already-audited doc content (previously sitting uncommitted in another
session's working tree), and rewrote the banner/audit note to describe the
current, more accurate state.

Why those 13 rows are still invisible (separate, pre-existing bug — not fixed here)

All 13 are declared via manifest macros MANIFEST_RE never matched, even
with the file-glob fix:

MANIFEST_RE = re.compile(r'\b(?:method|property)\(\s*"([^"]+)"\s*,\s*"([^"]+)"')
  • new AsyncLocalStorage(), new URLSearchParams(), new Worker(...) are
    declared via class("async_hooks", "AsyncLocalStorage") /
    class("url", "URLSearchParams") / class("worker_threads", "Worker")
    class( is never matched by MANIFEST_RE (only method(/property(
    are).
  • Buffer.allocUnsafeSlow is declared via
    internal_method("buffer", "allocUnsafeSlow", false, None)
    (crates/perry-api-manifest/src/entries/part_4.rs:111) — the \b
    word-boundary in MANIFEST_RE doesn't fire between _ and method, so
    internal_method(/internal_property(/internal_class( calls are
    invisible to the regex too.
  • stats.dev/.ino/etc. aren't manifest rows at all — they're populated
    via a packed key array (STATS_KEYS_REGULAR in
    crates/perry-runtime/src/fs/stats.rs), a fifth coverage shape the
    script's four recognized sources don't model.

Fixing MANIFEST_RE/adding a fifth coverage source is a separate, larger
change (would need care not to swing other modules the wrong way) and is
out of scope for this manifest-path fix. Left as a documented gap in the
updated audit note for a follow-up.

Test plan

  • python3 scripts/gen_parity_gaps.py (dry run, no --emit) —
    2232 covered / 286 gap, monotonically better than the broken
    1753/765 baseline across every module (no regressions)
  • Confirmed the fail-loud guards trip correctly (simulated zero
    matched files, and simulated only-entries.rs-matched with 0
    entries)
  • Did not run --emit; docs/runtime-parity-gaps.md's table/summary
    numbers are the hand-audited 2238/280, only the banner prose changed
  • No Rust files touched, so no cargo fmt/build needed

Summary by CodeRabbit

  • Documentation

    • Refreshed the Node.js runtime parity audit with updated coverage and gap totals.
    • Corrected multiple module gap listings (including URL, filesystem, buffer, worker threads, and async hooks) and retained/updated audit notes on verification status and potential staleness.
  • Bug Fixes

    • Improved parity report generation to reliably include all split manifest sources.
    • Added stronger validation to prevent incomplete manifest input from producing misleading results.
    • Adjusted text parsing/reading to use consistent encoding during regeneration.

The manifest was split from a single entries.rs into entries/part_1.rs
..part_4.rs on 2026-07-03 (to stay under the 2000-line CI gate), but
gen_parity_gaps.py's MANIFEST constant still pointed only at entries.rs,
which now just declares the `mod part_N;`s and concatenates them at
compile time. A dry run today parsed 0 manifest entries from the
now-mostly-empty file, undercounting coverage by ~480 entries (e.g.
node:os swinging from 0 gaps to 143).

Glob crates/perry-api-manifest/src/entries*.rs + entries/*.rs instead of
a hardcoded path, and fail loudly if the parsed entry count is
implausibly low, so a future re-split can't silently break this again.

docs/runtime-parity-gaps.md: land the 2026-07-16 hand-audited counts
(2238/280) that were sitting uncommitted, and rewrite the banner/audit
note to reflect the fixed script -- a dry run now lands at 2232/286,
recovering most but not all of the 16 hand-confirmed false positives
(13 remain uncounted because they're declared via the manifest's
class()/internal_method() macros or non-manifest dispatch paths that
the script's matcher doesn't recognize -- a separate, pre-existing gap,
out of scope here).
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aaf4292f-64ef-4e77-8469-041c4d8e0e73

📥 Commits

Reviewing files that changed from the base of the PR and between b6078af and 9674ba5.

📒 Files selected for processing (1)
  • scripts/gen_parity_gaps.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/gen_parity_gaps.py

📝 Walkthrough

Walkthrough

The parity generator now reads split manifest sources and validates coverage completeness. The runtime parity documentation updates aggregate counts, audit notes, and remaining gaps for several Node.js modules.

Changes

Runtime parity audit

Layer / File(s) Summary
Manifest source discovery and validation
scripts/gen_parity_gaps.py
The generator reads entries.rs and split entries/*.rs files, aggregates manifest members, validates plausible entry counts, uses explicit UTF-8 decoding, and updates the emitted source description.
Parity audit corrections
docs/runtime-parity-gaps.md
The audit documents the stale manifest-path issue and revises aggregate totals and remaining gaps for affected Node.js modules, including node:url, node:fs, node:buffer, and node:worker_threads.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • PerryTS/perry#5204: Introduced the parity generator logic that this PR updates for split manifest parsing.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: gen_parity_gaps now reads split api-manifest entries.
Description check ✅ Passed The description is detailed and covers the root cause, fix, examples, and test plan, but it omits the template's Related issue section.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/gen-parity-gaps-manifest-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/runtime-parity-gaps.md (1)

79-95: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Restore correct sort order for manually updated modules.

Because these module gap counts were updated manually, the document's structure is now out of sync with its stated sorting rule (descending by gap size, then ascending by module name). Modules that had their gaps reduced need to be moved down.

  • docs/runtime-parity-gaps.md#L79-L95: Reorder the summary table rows. node:url and node:fs (2 gaps) belong below timers/promises, node:buffer (5 gaps) belongs below trace_events, and node:async_hooks (0 gaps) belongs in the 0-gap section directly above diagnostics_channel.
  • docs/runtime-parity-gaps.md#L393-L418: Move the ### node:url and ### node:fs breakdown sections further down the document to correctly group them with the other 2-gap modules. Ensure the ### node:async_hooks section is completely removed if it is still present, as it now has zero gaps.
📝 Proposed correct order for the table rows
-| `node:url` | 47 | 2 | 49 |
-| `node:fs` | 180 | 2 | 182 |
 | `node:readline/promises` | 0 | 7 | 7 |
 | `node:assert` | 21 | 6 | 27 |
-| `node:buffer` | 103 | 5 | 108 |
 | `node:cluster` | 29 | 6 | 35 |
 | `node:events` | 35 | 6 | 41 |
 | `node:trace_events` | 0 | 6 | 6 |
+| `node:buffer` | 103 | 5 | 108 |
 | `node:crypto` | 133 | 5 | 138 |
 | `node:tty` | 15 | 4 | 19 |
 | `node:https` | 21 | 3 | 24 |
 | `node:child_process` | 35 | 2 | 37 |
+| `node:fs` | 180 | 2 | 182 |
 | `node:readline` | 27 | 2 | 29 |
 | `node:sqlite` | 50 | 2 | 52 |
 | `node:timers/promises` | 3 | 2 | 5 |
+| `node:url` | 47 | 2 | 49 |
 | `node:worker_threads` | 63 | 1 | 64 |
-| `node:async_hooks` | 29 | 0 | 29 |
 | `node:console` | 22 | 1 | 23 |
 | `node:dgram` | 27 | 1 | 28 |
 | `node:fs/promises` | 60 | 1 | 61 |
 | `node:http` | 140 | 1 | 141 |
 | `node:net` | 77 | 1 | 78 |
 | `node:stream` | 80 | 1 | 81 |
 | `node:zlib` | 90 | 1 | 91 |
+| `node:async_hooks` | 29 | 0 | 29 |
 | `node:diagnostics_channel` | 30 | 0 | 30 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/runtime-parity-gaps.md` around lines 79 - 95, Restore the documented
descending-gap, ascending-module sort order in docs/runtime-parity-gaps.md:
reorder the summary rows at lines 79-95 so node:buffer follows
node:trace_events, node:url and node:fs join the 2-gap group below
node:timers/promises, and node:async_hooks is placed in the 0-gap section above
diagnostics_channel. Move the node:url and node:fs breakdown sections at lines
393-418 to their matching 2-gap group, and remove the node:async_hooks breakdown
section entirely if present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/gen_parity_gaps.py`:
- Around line 147-149: Update the manifest-reading loop in the parity-gap
generation flow to explicitly read each file as UTF-8 by passing the encoding to
path.read_text(). Keep the existing MANIFEST_RE parsing and by_module population
unchanged.

---

Outside diff comments:
In `@docs/runtime-parity-gaps.md`:
- Around line 79-95: Restore the documented descending-gap, ascending-module
sort order in docs/runtime-parity-gaps.md: reorder the summary rows at lines
79-95 so node:buffer follows node:trace_events, node:url and node:fs join the
2-gap group below node:timers/promises, and node:async_hooks is placed in the
0-gap section above diagnostics_channel. Move the node:url and node:fs breakdown
sections at lines 393-418 to their matching 2-gap group, and remove the
node:async_hooks breakdown section entirely if present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 20c9606a-0e08-4f0b-80c9-1bcea97276dc

📥 Commits

Reviewing files that changed from the base of the PR and between 2e105ca and b6078af.

📒 Files selected for processing (2)
  • docs/runtime-parity-gaps.md
  • scripts/gen_parity_gaps.py

Comment thread scripts/gen_parity_gaps.py
read_text() without an encoding uses the locale codec, so on a Windows
runner (cp1252) reading UTF-8 Rust sources raises UnicodeDecodeError —
or, on the two readers that pass errors="ignore", silently mis-decodes
and drops rows from the gap report. Rust sources are always UTF-8; say
so. Reported by CodeRabbit on #6504.
@proggeramlug
proggeramlug merged commit 137cfef into main Jul 17, 2026
2 checks passed
@proggeramlug
proggeramlug deleted the fix/gen-parity-gaps-manifest-path branch July 17, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant