Skip to content

docs(webapi): document alpha and validate docs distribution [Codex] - #398

Draft
jderochervlk wants to merge 20 commits into
agent/alpha-binding-contractsfrom
agent/alpha-docs-distribution
Draft

jderochervlk wants to merge 20 commits into
agent/alpha-binding-contractsfrom
agent/alpha-docs-distribution

Conversation

@jderochervlk

@jderochervlk jderochervlk commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

This stacks the documentation/distribution work on binding-contract PR #399, which is itself stacked on tooling/release PR #397. It does not publish packages, create tags, close historical backlog issues, or change GitHub/npm settings.

For #393, the README and documentation landing pages distinguish the ReScript 13.0.0-alpha.5 tested baseline from the wider prerelease peer range, document the alpha breaking-change contract, provide a normal install/config/example, and state that the registry alpha tag still points to the older 0.1.0-alpha-b1d58f9 until an authorized alpha.1 publication. The candidate consumer is verified from its packed tarball. Contributor setup uses a fast-forward-only update workflow without destructive cleanup. Architecture, modelling, generation, documentation, and testing guides now describe the flat public API and current fixture/compiler/browser workflow. Project status reconciles #236, #237 and its now-closed slices #240-243, #27, #23, #4, and #5 without closing them or making them alpha gates. CHANGELOG.md records the binding migration contracts from the stacked branch, including typed bytes/audio buffers, WebCrypto helpers, empty and nullable results, operation-specific IndexedDB deletion, and DOM/SVG changes.

For #394, generated signature links resolve through the public API manifest and a unique public type alias owner; ambiguous/internal references remain unlinked. The examples link respects Astro's configured base path. npm run check:docs-links validates required docs routes, local HTML and SVG fragments, page/asset links (including CSS url()/imports and inline styles), and same-site absolute routes; fixtures cover base traversal, duplicate prefixes, comments/strings, escaped CSS identifiers, entity/percent fragments, and empty/incomplete artifacts. CI and the unprivileged release validation job run this checker immediately after the docs build. External URLs and canonical metadata are intentionally not verified by the local route checker.

For #395, repository history and actual WOFF2 metadata did not establish source release/version provenance or applicable licenses for the bundled Inter/Roboto Mono files. The binaries and their dead CSS/layout references are removed rather than assigning an unverified license. The site uses documented system sans-serif/monospace stacks; visual metrics can vary with the reader's installed fonts. The attribution page is emitted in the built docs, and the source-only npm package still excludes documentation assets.

The release guide covers the initial 1.0.0-alpha.1 version/tag, later synchronized package/lock bumps, release notes, the tested check sequence, exact-artifact validation and dry-run, main/manual publication guard, and post-publish dist-tag check. The npm trusted-publisher tuple is recorded, but npm account configuration/provenance setup remains an explicit maintainer-only check; #385 is not claimed fully complete by this documentation change. The local registry alpha tag is still on the prior prerelease, and no publication was performed.

Closes #393
Closes #394
Closes #395

@jderochervlk

jderochervlk commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator Author

Independent review — bdff32eaa9eeea8cdd8ac9e00488f9c996cba593

Reviewed against tooling base 77b59836d6ef1838795f78496f7dd89cd98816de, including the CSS-check follow-up after the initially requested 36ec0c0 snapshot. Keep draft / changes requested in this summary; this is not a same-account formal approval. No source files, settings, releases, or branches were changed.

Actionable findings

  1. P2 — Resolve relative references against the deployed page URL, including the base. scripts/check-doc-links.mjs:124–134. pageURL omits the deployment base, then the fallback accepts paths outside it. With base /docs/, documents index.html containing <a href="../guide/"> plus guide/index.html return [], although the browser navigates to /guide/, outside the deployment. Conversely href="docs/guide/" also falsely passes by stripping what is actually a duplicated prefix. Construct the source URL under the real normalized base and enforce containment after resolution. Also fix root-base normalization: / becomes //, incorrectly rejecting valid root-relative links. Add negative traversal/duplicate-prefix and root-base fixtures.

  2. P2 — Correct the historical disposition of Simplify package module/type structure #237 using its child issues, not its stale checkbox text. docs/content/docs/project-status.mdx:48–50. The page says fetch/file/canvas/URL/socket, capability access, media, and integration remain. Live Simplify fetch, file, canvas, URL, and socket module surfaces #240, Move runtime capability access away from Global window and navigator #241, Simplify media and device module surfaces #243, and Final integration for package simplification #242 are all closed, as are Simplify DOM, event, and observer module surfaces #238/Shared groundwork for package simplification #239. Record the completed slices and identify any concrete residual work separately; the open parent and unchecked historical list do not establish those slices remain unfinished. This is part of Document the ReScript 13 alpha contract and safe contributor workflow #393's explicit reconciliation acceptance.

  3. P2 — Tokenize CSS references rather than matching url() inside arbitrary text. scripts/check-doc-links.mjs:107–112. Both /* old: url(/docs/removed.woff2) */ and a::before { content: "url(/docs/not-a-link)" } produce missing-asset errors, despite neither requesting an asset. Conversely the valid escaped CSS function u\72l(/docs/missing.svg) is missed. Decode CSS escapes, ignore comments and non-URL string tokens, and do not HTML-decode raw stylesheet text. Add failing-target as well as successful fixtures; the new fixture only tests success.

  4. P2 — Restrict alias candidates to actual exported top-level types. docs/typeLinks.js:1–5. The regex scans comments and nested modules. /**\ntype example = Internal.real\n*/\ntype t = Internal.real suppresses the valid unique public t as ambiguous; a nested module Impl with type hidden = Internal.secret on its own indented line produces a nonexistent top-level PublicOwner#hidden target. Use exported documentation/compiler items, or a parser that excludes comments/nested declarations and respects interfaces; verify the candidate anchor exists before linking. These are reproduced parser-boundary defects, not a claim that the current site contains such broken alias links: all 77 current unique candidate anchors existed.

  5. P2 — Make fragment/attribute normalization browser-compatible and handle malformed escapes explicitly. scripts/check-doc-links.mjs:8–9 and 124–142. <a href="#caf%C3%A9"> targeting id="caf&#233;" incorrectly fails because numeric character references are not decoded. href="#%" or a malformed path escape throws URIError, aborting the whole audit without a source/reference diagnostic; a literal-percent fragment can itself be browser-valid. Use proper HTML entity decoding and explicit, tolerant/error-valued URI handling. Add Unicode/numeric-entity, literal-percent, malformed-path, and malformed-fragment fixtures.

  6. P2 — Fail when the supplied built artifact contains no HTML. scripts/check-doc-links.mjs:190–204. Running the CLI against an empty existing directory exits successfully with Validated ... in 0 built files. An asset-only directory likewise supplies no page-validation evidence. Require at least the expected entry page/HTML set before reporting successful validation, with empty/asset-only fixture tests.

  7. P2 — Make the release guide's exact-artifact local dry-run recipe achievable. docs/content/docs/contributing/releasing.mdx:45–49 instructs maintainers to use the archive produced by the workflow and forbids repacking. At this exact stack, the workflow packs into a runner-local .release directory and has no artifact upload/download step. Explain how the validated archive is retrieved, or reconcile this guidance after the foundation supplies artifact transfer. Do not imply that an independently repacked local archive is the same validated artifact.

Lower-priority cleanup / scope gaps

  • P3 — Orphan font references remain: docs/styles/fonts.css:1–7 through line 106 still reference all seven deleted WOFF2 files; unused docs/layouts/BaseLayout.astro:2 still imports @fontsource-variable/inter. Remove or reconcile these dead paths. They are not presently bundled: the built artifact contains no font binaries or active WOFF2 references.
  • P3 — Contributor architecture is only partially refreshed: api-module-structure.mdx:28–29 implies every interface owner exports t, which is not true for e.g. current FontFace/ResizeObserver. The companion module-type-structure.mdx:42–65 still teaches open DOMAPI and old paths; api-modelling.mdx:101 still anticipates a Vitest/happy-dom harness rather than the actual native-browser direction. Qualify the contract and refresh or clearly mark historical examples.
  • Additional explicit checker limits: only .html fragments are validated, so an existing icons.svg#missing passes; every scheme-bearing URL, including absolute same-site URLs, is excluded. Do not interpret a local-check pass as verification of those targets.

Acceptance and release gates

  • Document the ReScript 13 alpha contract and safe contributor workflow #393: partial, not ready to close. Compiler baseline/range, alpha-breaking contract, minimum candidate configuration/example, safe fast-forward update recipe, and restrained runtime/browser claims are supported. Historical/architecture corrections remain. The PR body explicitly says final binding migration reconciliation is pending: that is clear enough to explain draft status, not evidence that migration acceptance is complete. Keep it pending, put a corresponding warning in CHANGELOG.md:14–41, and reconcile the final bindings before readiness. In particular the current notes do not yet cover the listed Web Audio breaking typed-buffer contracts or the nullable/empty/IndexedDB result migrations from Represent native empty, nullable, and operation-specific results accurately #392. Those should not disappear merely because the final branch is still in progress.
  • Live installation is not yet candidate acceptance: README.md:16–17 currently installs registry alpha = 0.1.0-alpha-b1d58f9, whose peer is rescript >=13; the exact first README command failed with ETARGET. The new candidate tarball succeeds. Label the registry command as applicable after the separately authorized candidate publication, and do not claim it is a live installation pass now. This is not a request to publish during review.
  • Resolve generated API links to public pages and check built documentation #394: actual generated-site repair works, checker acceptance remains partial. Public-page filtering is retained, no top-level internal *Types routes leak, the example guide link contains the correct deployment base, and current emitted local links/fragments pass. The counterexamples above show remaining false-green/false-failure behavior.
  • Include provenance and license notices for bundled documentation fonts #395: system-font alternative satisfies the distribution/license goal. The seven unverifiable binaries are gone; the attribution page is emitted/discoverable; the site uses system stacks; the checked npm tarball excludes docs/fonts/tools. No guessed Inter/Roboto license needs to be assigned to binaries that are no longer distributed. Dead-reference cleanup remains.
  • Release/trust: not verified. The guide correctly calls npm account settings unverified and restricts alpha guidance to the alpha dist-tag. I did not verify trusted publishing, successful provenance-bearing publication, or external-site availability. Also, the pinned foundation still has one publish job granting id-token: write to PR/dry-run validation; the isolation described in test(webapi): harden runtime and release validation [Codex] #397's body is not present in the reviewed YAML. This is inherited foundation work, not introduced by the three-line integration here; keep that tooling/release gate open and re-review after the stack updates. Registry dist-tags do not prove publisher trust or provenance.

Evidence

All validation ran in disposable scratch copies of the exact commits, leaving the attached source worktree untouched (its pre-existing deletion of tests/index.js remains unchanged). Local toolchain: Node 24.16.0 / npm 11.15.0 / ReScript 13.0.0-alpha.5, not the CI Node 26 environment.

At bdff32e: npm run build, npm run build:docs, npm run check:docs-links (9 fixtures; 307 HTML pages / 675 built files), npm run format:check, and npm run check:consumer passed. The consumer check validated 343 tarball files, supported installation, unsupported-peer rejection, default/Fetch/SafeFetch compilation, feature rejection, runtime smoke, and the registered negative diagnostic fixture. Separately compiled the README's exact minimal configuration/example against the candidate tarball; it succeeds. Ran the edge-case probes described above. An independent HTMLParser audit of the unchanged generated HTML also checked local fragments; its only additional missing same-site URL was Astro's absolute canonical /404/ versus emitted 404.html, not a newly broken navigation link.

I did not run the full Node/browser suites, feature suite, Node 26 toolchain, or a browser compatibility matrix. External links are outside the local check; in particular the new GitHub main/CHANGELOG.md link is currently 404 before merge. That pre-merge fact is not a permanent broken-link finding, but it is also not validated by the local link gate.

@jderochervlk
jderochervlk changed the base branch from agent/alpha-tooling-release to agent/alpha-binding-contracts November 7, 2026 01:21
@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Independent re-review — 42b464d9 against d938c719

Keep draft for the checker findings below; no formal approval. Review only: no repository edits, merges, settings changes, tags, publication, or issue closures.

The prior bdff32e examples are fixed. The exact diff remains docs/distribution plus additive docs-link/format/package/CI/release integration; no binding, dependency-lock, or test-runner changes. The binding base contains frozen foundation 6fa3016a. Deployment-prefix resolution (including traversal/duplicate-prefix/root fixtures), non-throwing malformed escapes, numeric entities/literal-percent fragments, required routes, same-site links, HTML/SVG targets, CSS comment/string exclusion and escaped url() identifiers all work for the tested cases. External and canonical metadata exclusions are explicit.

Remaining findings beyond the 21 passing fixtures

  1. P2 — srcset still both misses requests and invents URLs. check-doc-links.mjs:112–132. <img srcset="data:image/svg+xml,%3Csvg%3E, /docs/missing.svg 2x"> returns no errors with only index.html, but Chromium requests /docs/missing.svg. Conversely /docs/a,b.svg 1x is one valid URL; with a,b.svg present, the checker invents missing a and b.svg. Follow the srcset URL/trailing-comma tokenization rule rather than special-casing data URLs.
  2. P2 — fragment normalization is still not browser-compatible. 303–308. href="#caf%C3%A9%" targeting id="café%" is rejected: one literal percent causes all decoding to be abandoned. Chromium resolves it to that target. Decode valid byte escapes tolerantly rather than falling back for the entire string. Separately, the limited HTML entity decoder still rejects the equivalent target id="caf&eacute;".
  3. P2 — alias discovery still mistakes non-declarations for public types. typeLinks.js:1–66. A valid nested comment /* outer\n/* inner */\ntype example = Internal.secret\n*/ yields a fake alias; so does a multiline backtick string containing type hidden = Internal.secret at line start. Both constructs compile under alpha.5. Track nested comment depth and mask string contents, or use compiler-exported items. All 88 current unique alias targets exist; this is a parser-boundary regression gap, not a claim of current broken generated targets.
  4. P3 — escaped CSS import names bypass validation. 262–269. @\69mport "missing.css"; falsely passes; Chromium requests the missing stylesheet. Decode at-keyword identifiers as well as function identifiers.

Other acceptance results

Evidence and limits

Independent scratch-copy passes on Node 24.16.0 / npm 11.15.0, not local Node26: npm ci; format:check; build; npm test; WEBAPI_TEST_PORT=4192 npm run test:browser (4 tests, including socket/worker); check:features (28); test:negative; check:consumer (343 packed files); check:release (unpublished alpha.1); build:docs/check:docs-links (307 HTML/675 files, 21 fixtures). Additional Chromium/parser probes produced the findings above.

Live head CI is complete: CI/build SUCCESS; Release/validate SUCCESS; deploy-docs and publish SKIPPED. No external-link availability, unpublished-candidate registry installation, npm account settings, provenance-bearing publication, local Node26 execution, or full browser matrix was verified.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Independent final review — 1d212449 against d938c719

At the requested snapshot: keep draft; four P2 checker/parser findings remain. No formal same-account approval.

Snapshot scope: while preparing this comment, the live PR head advanced to b9f906310b2406071b37739fc88e84cbd855a4ef. That newer head has not been reviewed here. Every finding and validation result below is pinned to the requested 1d212449ef07ad571f7ec29c36588117d3006ad4 against d938c719b016e439aeeec3da2d185dcd0b4e714f; this is not a verdict on b9f90631. Reviewed the exact requested head/base; #399 still supplies the binding base, which includes frozen tooling 6fa3016a. The diff changes documentation/distribution and adds checker/format/package/CI/release integration; it does not change bindings, the dependency lock, or the runtime runner. No repository files, branches, settings, releases, tags, or issue states were changed during this review. This summary is the only GitHub write.

The reviewed generated site is clean: an independent HTMLParser audit of 307 HTML pages checked 133,169 local page/asset references with no missing target/HTML anchor, excluding external URLs and canonical metadata. All 88 current unique alias targets have real built anchors; no internal implementation routes were exposed. The findings below concern reproducible validator/parser behavior, not newly discovered broken links in the current site.

Actionable findings

  1. P2 — srcset still misses requested assets and splits valid filenames. scripts/check-doc-links.mjs:119–131. With only index.html, <img srcset="data:image/svg+xml,%3Csvg%3E, /docs/missing.svg 2x"> returns [] under /docs/: after consuming the data URL, the descriptor-skipping loop consumes the next candidate too. Chromium at device scale factor 2 selects and requests /docs/missing.svg. Conversely /docs/a,b.svg 1x is one valid candidate, but the checker reports missing a and b.svg despite a,b.svg being present. Use the srcset URL/trailing-comma tokenization rules for all schemes; add both negative and valid-comma fixtures. This remains from the prior re-review.

  2. P2 — fragment and HTML-entity normalization still rejects valid anchors. decodeFragment:307–312 and decodeHTML:9–24. href="#caf%C3%A9%" targeting id="café%" is rejected because one literal % prevents decoding the valid escapes. href="#caf%C3%A9" targeting id="caf&eacute;" also fails because the named entity is not decoded. Chromium resolves both to the intended :target. Use tolerant percent/UTF-8 decoding and browser-compatible HTML entity decoding; add these combined cases, not only isolated numeric-entity/literal-percent cases. Both remain from the prior re-review.

  3. P2 — alias discovery still treats nested comments and multiline strings as declarations. docs/typeLinks.js:23–29 and 39–67. /* outer\n/* inner */\ntype example = Internal.secret\n*/ yields a fake public example alias. A multiline backtick string containing type hidden = Internal.secret at line start yields a fake hidden alias. Both constructs compile under alpha.5. Depending on ownership, this can create a nonexistent public anchor or suppress a valid unique owner as ambiguous. Track nested comment depth and mask string contents, or use compiler-exported items; retain the built-anchor check. This remains from the prior re-review; the 88 real current targets are valid.

  4. P2 — CSS URL tokens incorrectly discard comment-like URL text. scripts/check-doc-links.mjs:219–243. For site.css containing .x{background:url(/*old*/assets/icon.svg)}, with assets/icon.svg present, the checker returns []. Chromium requests /*old*/assets/icon.svg, outside /docs/, not /docs/assets/icon.svg. Inside an unquoted CSS URL token, /*old*/ is URL text, not a CSS comment to remove. Likewise url(assets/*old*/icon.svg) is rewritten to assetsicon.svg, inventing a different target. Apply CSS Syntax token boundaries before comment skipping and preserve unquoted URL contents. Add success and failure fixtures for these browser-confirmed cases. The scanner also starts in the middle of non-ASCII/dimension tokens (éurl(...) / 1url(...)), inventing asset requests Chromium does not make; cover token boundaries as part of the same correction.

Lower-priority follow-ups

  • P3 — exclusion normalization: isExternal:26–31 does not trim browser-ignored surrounding URL whitespace. <a href=" https://other.invalid/docs/missing/"> is incorrectly checked as a local missing route. Canonical exclusion:139 is case-sensitive although HTML rel keywords are case-insensitive: rel="CANONICAL" is checked rather than excluded. Normalize before classifying. Current emitted canonical metadata is lowercase and normal external references are excluded correctly.
  • P3, inherited — philosophy snippets: philosophy.mdx:26–30 and 50–55 still use bare document after open WebAPI.DOM. The exact first snippet fails alpha.5 compilation: document resolves to deprecated Stdlib.document, whose type is incompatible with WebAPI.DOM.document. Bind let document = WebAPI.DOM.window->WebAPI.Window.document. These lines are unchanged against the requested base; this is a follow-up, not a new blocking regression.

Accepted corrections and issue readiness

  • Document the ReScript 13 alpha contract and safe contributor workflow #393 — substantive documentation acceptance is supported, with the inherited philosophy follow-up above. The README minimal configuration/example compiles against the actual candidate tarball. Tested baseline versus peer range, alpha breaking changes, browser limitations, safe fast-forward update, architecture/modelling/generation/testing guidance, and historical dispositions are coherent. Live Rename overloaded constructor bindings from numbered make* names to semantic from* names #236/Simplify package module/type structure #237/Improve generated overloads #27/API overview #23/How to model Errors #4/Consider adding useful extension module #5 remain open; Simplify DOM, event, and observer module surfaces #238–243 are closed, correctly distinguished from the stale parent checklist. ReadableStream's optional strategy is correctly called out. The changelog matches incorporated Fix receiver dispatch for WebSocket sends and worker Request fetches #386–392 source and tests, including WebAudio/DOMMatrix buffers, crypto unknown/fixed-shape helpers and deriveBits/wrapKey, nullable/empty/IDB results, and DOM/SVG/constructor/Notification contracts. No further blocking migration gap found.
  • Resolve generated API links to public pages and check built documentation #394 — actual generated-site repair works, checker acceptance is not complete. Base/root-base/traversal/duplicate-prefix behavior, normal same-site absolute links, HTML/SVG fragments, comments/script exclusion, existing percent/numeric fixtures, and regular CSS/escaped url()/escaped @import cases pass. The new escaped-import fix works. The four P2 findings above prevent final acceptance of the checker.
  • Empty-artifact CLI/environment behavior works in the tested environment: independent invocations from a different working directory reject empty, asset-only, zero-byte-required-page, and whitespace-required-page artifacts with status 1 and clear required-page diagnostics. Complete nonempty required routes pass. The new subprocess fixture passes; no separate environment defect found on Node 24/Linux.
  • Include provenance and license notices for bundled documentation fonts #395 — ready under the permitted system-font alternative. The seven binaries, dead fonts.css, and unused BaseLayout are removed. The built attribution route is discoverable, explains unverified provenance and visual variation, and system font stacks are active. No font binaries exist in dist; remaining /fonts/inter.woff2 text is illustrative FontFace example code, not a loaded/distributed asset. The 343-file npm artifact retains the source-only boundary and excludes docs/fonts/tools.
  • Release guidance is now achievable and consistent with frozen tooling. Initial alpha.1/tag and later synchronized bumps/changelog/tags, the local exact-artifact check/dry-run recipe, internal artifact transfer, main/manual guard, alpha/not-latest verification, and WEBAPI_TEST_PORT=4192 behavior match the implementation. The exact documented local pack/check/dry-run sequence passed. Publish explicit numbered v1.0.0 alpha versions safely #385 account-level trusted publishing remains explicitly unverified. Registry alpha still points to 0.1.0-alpha-b1d58f9; candidate publication/live registry install is not claimed. No publication or settings verification occurred.

Validation and limits

All builds/probes ran in disposable scratch copies of the exact head, not the attached source worktree. Toolchain: Node 24.16.0 / npm 11.15.0 / ReScript 13.0.0-alpha.5, not local Node26.

Passed: npm ci; npm run format:check; npm run build; npm test; WEBAPI_TEST_PORT=4192 npm run test:browser (4 Chromium tests); npm run check:features (28 definitions plus fixtures); npm run test:negative; npm run check:consumer (343 files); npm run check:release (6 fixtures/unpublished candidate); npm run build:docs; npm run check:docs-links (24 fixtures/675 built files); exact-artifact npm run check:consumer -- "$artifact" and npm publish "$artifact" --access public --tag alpha --dry-run --ignore-scripts; standalone README candidate compilation; parser-boundary compilation and Chromium reproduction probes. git diff --check passed and the attached worktree remained clean at the requested head.

Checks for reviewed commit 1d212449 are complete: CI/build SUCCESS; Release/validate SUCCESS; deploy-docs and publish SKIPPED. Local Node26 execution, a full browser-engine/version matrix, external-link availability, npm account settings, provenance-bearing publication, and live installation of the unpublished candidate were not verified.

Final readiness at 1d212449: not acceptance-ready until the four P2 checker/parser cases are fixed or explicitly removed from its promised acceptance scope. The docs/migration and font work are supported; neither green CI nor a clean current generated site resolves the reproducible validator gaps.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Independent follow-up review — b9f906310b2406071b37739fc88e84cbd855a4ef

Reviewed against exact base agent/alpha-binding-contracts at d938c719b016e439aeeec3da2d185dcd0b4e714f, following the review of 42b464d9. Keep draft for the two P2 checker findings below. There is also a lower-priority fragment-decoding edge case. This is a summary comment, not a formal review or same-account approval. No source edits, merges, tags, publication, settings changes, or issue closures were performed.

Actionable findings

  1. P2 — Decode named HTML entities completely and case-sensitively. scripts/check-doc-links.mjs:9–18. Adding eacute fixes the exact earlier example, but the small allowlist still rejects valid targets such as <a href="#sch%C3%B6n">go</a><p id="sch&ouml;n">target</p>. More importantly, /gi plus lowercasing makes distinct named entities equivalent: <a href="#caf%C3%A9">go</a><p id="caf&Eacute;">target</p> returns [], although the actual ID is cafÉ, not café, and Chromium has no :target. This is both a false failure and a false green, reproduced in Chromium. Use HTML attribute character-reference semantics rather than extending a case-insensitive allowlist; add matching and mismatching named-entity fixtures.

  2. P2 — String masking now breaks the subsequent nested-declaration mask. docs/typeLinks.js:21–33, interacting with 49–67. The first pass preserves the opening quote but masks its closing quote. The second pass then remains in string mode and stops tracking following braces. With backing types defined, this valid alpha.5 source:

    let example = "text"
    module Impl = {
    type hidden = Internal.secret
    }
    type t = Internal.real

    produces both PublicOwner.hidden and PublicOwner.t aliases. Only t is top-level; the invented owner can create a nonexistent PublicOwner#hidden link or suppress a real unique owner as ambiguous. The same failure occurs after a backtick string. I compiled the reproducer and compared parsers: 42b464d9 correctly returns only t; this head incorrectly adds hidden. Preserve balanced string delimiters for the second pass, remove string syntax entirely from its input, or unify the lexical passes. Add a fixture with a string before a nested module, not only a fake type inside a string. All 88 current unique alias target anchors nevertheless exist; this is a demonstrated parser regression, not a claim of an already-broken emitted alias link.

  3. P3 — Fragment decoding still abandons valid UTF-8 bytes adjacent to invalid byte escapes. scripts/check-doc-links.mjs:306–313. The earlier #caf%C3%A9% → café% case is fixed. However, href="#caf%C3%A9%FF%" targeting id="café�%" is rejected: the contiguous %C3%A9%FF run throws and is preserved wholesale. Chromium performs forgiving UTF-8 decoding and selects that target. Decode percent bytes with replacement for invalid UTF-8, preserving literal malformed percent characters, and cover mixed valid/invalid byte sequences.

Earlier findings and test strength

  • Exact prior srcset probes now work: a descriptorless data URL followed by /docs/missing.svg 2x reports the missing asset, and /docs/a,b.svg 1x remains one URL. Chromium independently requested those exact candidates.
  • Exact nested-comment and multiline-backtick fake-alias examples are fixed. The new regression in finding 2 appears when a later nested declaration follows a string.
  • Escaped @\69mport "missing.css" is now detected; Chromium independently requested it. The new negative import fixture guards against silently ignoring it.
  • Empty required pages now fail at the actual CLI boundary with a specific diagnostic; this is not just a helper assertion or an unrelated subprocess failure.
  • All 27 fixtures pass despite the findings. The named-entity fixture exercises only eacute; the alias fixture does not exercise nesting after a string. Also retain the exact descriptorless-data-URL regression as its own negative fixture: the new combined srcset fixture uses a 1x descriptor, so it does not directly guard the old data-URL delimiter bug. Similarly, a nested-comment fixture should place a fake declaration after the inner comment closes but before the outer one closes.

Documentation, distribution, and scope

Checks and limitations

All local builds/tests ran in a disposable archive of the exact head, using Node 24.16.0 / npm 11.15.0 / ReScript 13.0.0-alpha.5, not the CI Node 26 environment. Passed: npm ci; npm run format:check; npm run build; npm test; WEBAPI_TEST_PORT=4192 npm run test:browser (4 tests); npm run check:features (28 feature definitions); npm run test:negative; npm run check:consumer (343 packed files); npm run check:release (unpublished alpha.1); npm run build:docs; npm run check:docs-links (27 fixtures). Additional Chromium 156.0.8078.4 probes, compiler reproducer, README packed-consumer compilation, alias-anchor inspection, and independent HTML audit are described above.

Live exact-head checks are complete: CI/build SUCCESS; Release/validate SUCCESS; deploy-docs and publish SKIPPED. I did not verify external-link availability, Bun installation, a live registry installation of the unpublished candidate, npm account settings, provenance-bearing publication, local Node 26 execution, or a Firefox/WebKit/version compatibility matrix. No formal approval or issue closure is implied.

This branch has not been deployed

No deployments
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