Skip to content

docs(webapi): update alpha guides and fix broken links [Codex] - #398

Merged
jderochervlk merged 19 commits into
mainfrom
agent/alpha-docs-distribution
Nov 8, 2026
Merged

jderochervlk merged 19 commits into
mainfrom
agent/alpha-docs-distribution

Conversation

@jderochervlk

@jderochervlk jderochervlk commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Updates installation and contributor guides for ReScript 13 alpha. Adds migration notes for #399 and a release guide.

Fixes broken API links and adds automated checks for links within the built site. Replaces bundled fonts with system fonts because their source and licenses could not be verified.

Builds on #399, after #397, and completes the documentation requirements for the issues below. npm Trusted Publishing still needs maintainer verification (#385).

Closes #383, closes #387, closes #388, closes #390, closes #391, closes #392, closes #393, closes #394 and closes #395. Refs #385.

@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 build(webapi): fix alpha installs and release checks [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.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Independent final supplemental review summary — aa0ad652 against f5f7d338

Summary only — not a formal approval. Reviewed exact head aa0ad65218cbd124c26237fd60c19fa1581b7862 against final binding base agent/alpha-binding-contracts at f5f7d338794ffd74dcc32f69d238e0059d611cbc. Both still match the live PR. This review independently inspected current files and reran validation; it does not inherit earlier review results.

Outcome: all specifically requested past checker/parser findings are fixed. I found no remaining P1/P2 blockers in the requested docs/distribution scope. One additional non-blocking P3 fragment edge case remains below; a passing checker is not a claim of full browser/parser equivalence.

Remaining finding

P3 — Preserve U+FEFF when decoding fragment bytes. At check-doc-links.mjs:299–305, each percent-byte run is decoded with a fresh default TextDecoder. Its BOM handling strips a leading %EF%BB%BF, even in the middle of an ID. Reproducer:

<a href="#caf%EF%BB%BF%C3%A9">go</a>
<p id="caf&#xFEFF;é">target</p>

The checker reports a missing #café; Chromium correctly targets the ID containing U+FEFF. Conversely, replacing the ID with plain café makes the checker return [], while Chromium has no :target. Both directions were independently reproduced. Use UTF-8 decoding that preserves the BOM as a character, such as new TextDecoder("utf-8", { ignoreBOM: true }), with positive and negative fixtures. This uncommon case does not affect the current generated site's audited links. I classify it as a low-priority follow-up, not a renewed blocker for the earlier UTF-8-adjacency correction.

Requested past findings: independently confirmed fixed

  • srcset: the exact descriptorless data:image/svg+xml,%3Csvg%3E, /docs/missing.svg 2x case now reports the missing second candidate. An ordinary /docs/a,b.svg 1x remains one valid URL. Chromium selected/requested both expected candidate URLs in separate images. The exact descriptorless regression now has its own negative fixture.
  • HTML attribute character references: the checker uses the full, case-sensitive entities attribute decoder, not an expanding allowlist. Matching &ouml;, mismatching &Eacute; versus lowercase é, numeric references, multi-code-point &NotEqualTilde;, numeric replacement semantics, and ambiguous semicolonless &oumlX / &ouml= behaved correctly in the independent probes. Browser comparisons confirmed the case-sensitive and ambiguous-attribute cases.
  • Important correction to the reviewer claim about caf&amp;eacute;: in an HTML attribute this becomes the literal text caf&eacute;, not café. Character references are not recursively decoded. Chromium and the checker agree: #caf%C3%A9 does not target id="caf&amp;eacute;"; #caf%26eacute%3B does. By contrast, id="caf&eacute;" is café. The current negative fixture is correct; it should not be reversed into a success expectation.
  • Percent fragments: #caf%C3%A9%FF% targets café�%, preserving valid adjacent UTF-8 and the literal malformed percent. Independently confirmed in Chromium. The earlier #caf%C3%A9% case also passes.
  • ReScript alias discovery: a fake declaration after an inner comment closes but before the outer comment closes is ignored. Both a quoted string and a backtick string followed by a nested module alias produce only the genuine top-level t alias. The two backing-type/string/nested-module reproducer sources also compile under alpha.5. All 88 current unique alias targets have actual built anchors.
  • CSS: comment-like text inside url(/*old*/assets/icon.svg) and url(assets/*old*/icon.svg) is preserved. The former is correctly rejected as outside /docs/; the latter can resolve to the literal path containing /*old*/. éurl(...) and 1url(...) do not invent asset requests. Escaped @\69mport is checked. Chromium request capture independently confirmed the real URLs/import and absence of requests for the non-URL tokens.
  • Artifact boundary: actual CLI subprocesses, launched from a different working directory, reject empty, asset-only, missing-required-route, zero-byte-required-page, and whitespace-only-required-page artifacts with status 1 and relevant diagnostics. A complete nonempty four-required-page artifact succeeds. Base/root/traversal/duplicate-prefix, same-site links, SVG targets, canonical/external exclusions, and CSS/comment/string fixtures also pass.

Acceptance mapping and scope

  • Document the ReScript 13 alpha contract and safe contributor workflow #393 — supported. Tested alpha.5 versus the wider prerelease peer range, breaking-alpha policy, normal installation/configuration/example, candidate-versus-registry caveat, runtime/browser limitations, safe fast-forward contributor workflow, current flat architecture/testing guidance, changelog, and linked release runbook are present. The exact README configuration and ReScript sample compile against the actual candidate tarball. The two previously problematic philosophy examples now derive document explicitly and compile (only unused-open warnings remain). 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 are still open; Simplify DOM, event, and observer module surfaces #238–243 are closed, matching the recorded dispositions rather than the stale parent checklist.
  • Migration reconciliation uses the current final f5f7d338 bindings. CHANGELOG.md:31–42 correctly describes algorithmString / parameter-preserving algorithmObject, binary sign/digest/deriveBits/wrapKey results, boolean verify, unknown generic generation/export, fixed-HMAC generateKeySymmetric, fixed-ECDSA generateEcdsaKeyPair, and restricted binary/JWK export helpers. Typed byte/audio/DOMMatrix buffers, nullable/empty/IndexedDB results, and DOM/SVG/constructor/Notification changes are also covered. Current Crypto packed-consumer and negative contracts pass; no additional blocking migration gap found.
  • Resolve generated API links to public pages and check built documentation #394 — supported for the intended built-site gate, with the P3 caveat above. Public-manifest/unique-owner linking retains internal-module filtering; the examples testing link honors the deployment base. The new check is immediately after the docs build in both CI and unprivileged release validation. Rebuilt output contains 307 HTML pages / 675 files and passes all 34 checker fixtures. An independent browser-DOMParser audit checked 133,192 local HTML attribute references/fragments with zero errors; this separate audit does not itself cover CSS/srcset, which were probed separately. Examples → testing-guide → font-attribution navigation also succeeded in Chromium.
  • Include provenance and license notices for bundled documentation fonts #395 — supported via the explicitly allowed system-font alternative. All seven old binaries, dead font CSS, and unused layout references are removed. System sans/mono stacks are active; the emitted, discoverable attribution explains the provenance uncertainty and visual variation without guessing licenses. The built artifact has no font binaries and the navigation check requested no fonts. The 343-file npm tarball excludes docs, fonts, tools, tests, and scripts.
  • Dependency ownership and diff boundary are correct. entities@4.5.0 is already a direct pinned root devDependency in the specified tooling-containing base; this PR does not introduce a dependency/lockfile delta or a consumer runtime dependency. The 36-file diff is docs/distribution plus narrowly additive checker/Astro/package-script/format integration and three added lines in each CI/release workflow. No changes to src/, tests/, tools/, rescript.json, package-lock.json, or existing consumer/release-checker implementations.
  • Release runbook matches current tooling. Initial alpha.1/version/tag, synchronized later bumps, local pack-once path, same-tarball consumer check, dry-run-only versus real publication paths, internal exact-artifact transfer, unprivileged validation/separate main-only OIDC publish job, alpha/not-latest verification, and alternate browser port are consistent. Account-level trusted-publisher configuration remains explicitly unverified; this is not proof that Publish explicit numbered v1.0.0 alpha versions safely #385 is complete. Registry alpha still resolves to 0.1.0-alpha-b1d58f9, not the candidate. No request to publish is implied.

Checks, environment, and limitations

All builds/probes used a disposable archive of the exact head; the attached source worktree remains clean. Local toolchain: Node 24.16.0 / npm 11.15.0 / ReScript 13.0.0-alpha.5 / Chromium 156.0.8078.4, not local Node 26.

Passed: npm ci; npm run format:check; npm run build; npm run check:features (28 definitions plus fixtures); npm run test:negative; npm test; npm run check:consumer; npm run check:release (6 fixtures/unpublished candidate); npm run build:docs; npm run check:docs-links (34 fixtures/675 files); npm pack and npm run check:consumer -- "$artifact" against that exact archive; exact README packed-consumer compilation; independent parser/browser/artifact probes; and git diff --check.

The exact documented WEBAPI_TEST_PORT=4192 npm run test:browser was attempted but correctly refused to reuse an occupied server. WEBAPI_TEST_PORT=42983 npm run test:browser passed all 4 tests; this is an alternate-port run, not a claim that the 4192 invocation passed.

Live checks for this exact head are complete: CI/build SUCCESS; Release/validate SUCCESS; deploy-docs and publish SKIPPED. No local npm publish command, including dry-run, was executed. External-link availability, Bun installation, live registry installation of the unpublished candidate, npm account settings, provenance-bearing publication, local Node 26 execution, and Firefox/WebKit/version matrices were not verified.

No repository edits, merges, tags, releases, issue changes, settings changes, publication, or formal review/approval were performed. This summary comment is the only GitHub write.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Author verification summary for #393–#395 (this is an implementation/validation report, not a formal review approval or request to land):

  • Document the ReScript 13 alpha contract and safe contributor workflow #393 — Alpha and contributor guidance: README/docs state that ReScript 13.0.0-alpha.5 is the tested compiler baseline, distinguish it from the admitted prerelease peer range, and explain the alpha breaking-change policy. The default install/config/example was compiled from the packed candidate. Contributor architecture/testing guidance, safe update workflow, historical issue dispositions, and migration notes were reviewed against the final stacked bindings snapshot. No stable compiler is required for this alpha. The registry alpha tag still points to an older release; this candidate has not been published.
  • Resolve generated API links to public pages and check built documentation #394 — Public type links and built-doc checks: generated links resolve to unique public API owners/anchors, ambiguous/internal types remain unlinked, and the examples guide link honors the deployment base. npm run check:docs-links verifies built local routes, assets, fragments, required pages, and parser boundary fixtures. The final build had 307 HTML pages / 675 files; 35 checker fixtures passed. External URLs and canonical metadata are intentionally excluded from the checker. An independent reviewer also audited built local HTML references; that does not validate external links or every browser/parser edge case.
  • Include provenance and license notices for bundled documentation fonts #395 — Font distribution: bundled Inter/Roboto Mono binaries were removed because provenance/license facts could not be established. The site uses documented system font stacks, with platform-dependent visual metrics noted. The built attribution page is present, and the built docs contain no font binaries. The npm artifact remains source-only.
  • Publish explicit numbered v1.0.0 alpha versions safely #385 — Release runbook contribution: the guide documents initial/subsequent alpha version and tag steps, changelog/release notes, exact-artifact validation/dry-run, the main/manual-only publish guard, post-publish dist-tag verification, and the Trusted Publishing UI tuple. This documents the procedure; npm account-level trusted-publisher/provenance configuration remains maintainer-only and unverified, so Publish explicit numbered v1.0.0 alpha versions safely #385 is not claimed fully complete. No publish, tag, or registry change was performed.

Local validation on Node 24.16.0 / npm 11.15.0: fresh npm ci; npm audit (0 vulnerabilities); direct entities@4.5.0 manifest/lock verification; npm run format:check; npm test; WEBAPI_TEST_PORT=4193 npm run test:browser (4 Chromium tests); npm run check:features (28 definitions); npm run test:negative; npm run check:consumer (343-file packed candidate, including Crypto); npm run check:release; npm run build; npm run build:docs; npm run check:docs-links (35 fixtures); built artifact check for attribution/no font files; and git diff --check. External URL availability, Bun, other browser engines, npm account settings/provenance publication, and local Node 26 were not tested.

GitHub checks on this exact head: CI/build and Release/validate succeeded; deployment and publication jobs were skipped. PR head 8c121955e29673554489d3498131342a8a58144f; base agent/alpha-binding-contracts at fb9d51cbfcd5c1964bcc1c65c534d626e485c06d. The docs diff contains no binding, runtime/browser test, or ReScript configuration changes.

@jderochervlk
jderochervlk marked this pull request as ready for review November 7, 2026 16:36
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-08T18:19:11.491812Z fa4931f New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Supplemental independent review — final 6949c42c against 14f5873f

Summary comment only — not a formal review or approval. Reviewed exact #398 head 6949c42cc17269575b9db4df08c6190bc0824ab8 against #399 base agent/alpha-binding-contracts at 14f5873fc453e8d409244fd79a2afd71e9f25571. Both still match the live PR refs at the final check.

Recommendation: the requested supplemental checks support readiness for maintainer review; no new P1/P2 blocker found in this scope. This is not authorization to merge or publish.

HTTP-body stream contracts and migration

  • Exact signatures are byte-only: BodyInit.fromReadableStream is ReadableStream.t<Uint8Array.t> => t; Response.fromReadableStream is (ReadableStream.t<Uint8Array.t>, ~init: responseInit=?) => t with the native Response constructor.
  • Both registered negative fixtures explicitly instantiate WebAPI.ReadableStream.t<string>. The exact-head packed-consumer negative suite passes. Independently compiling each fixture in an isolated packed consumer fails at the helper argument with string versus Uint8Array.t, rather than an unrelated setup failure. Restoring only those two signatures to hypothetical old ReadableStream.t<'chunk> inputs in that disposable installed package makes each exact fixture compile successfully. Both fixtures therefore discriminate the new contract from the old generic one. No tracked source was changed for this experiment.
  • Positive byte-stream conversions through both adapters compile, including the existing BindingByteTypes and browser fixtures. The exact generic docs ReadableStream.t<string> / make() / getReader snippet also compiles in the packed consumer. Ordinary ReadableStream construction/reader APIs remain generic; the source documentation correctly describes the optional queuing strategy.
  • All 4 Chromium tests pass. A separate probe imports the actual compiled ReScript browser-contract module and checks the exported responseStreamBytes: it is a native Uint8Array with all three bytes [65, 66, 67] after Blob.stream -> Response.fromReadableStream -> Response.bytes. This supplements the fixture's length/endpoint assertions with an exact whole-content assertion.
  • The new CHANGELOG.md:23–25 migration note matches these results: only the HTTP-body adapters require byte chunks; ReadableStream itself remains generic. The generic stream docs remain accurate and should not be rewritten to imply all streams are byte-only.

Diff boundary and prior checker/dependency work

  • Against the exact final base, the 37-file diff remains docs/distribution plus checker/Astro/format/package-script integration, three added lines in each CI/release workflow, and the direct pinned entities@4.5.0 devDependency. The lockfile delta is only the corresponding root devDependency entry; it does not introduce a new resolved package record or consumer runtime dependency.
  • There are no differences against that base in src/, tests/, tools/, rescript.json, Playwright configuration, the negative-fixture registry/files, or existing consumer/release-checker implementations. The Preserve Uint8Array types in Fetch, Blob, and SafeFetch byte APIs #388 binding/test changes seen since the prior docs head are inherited from fix(webapi): correct browser API types and calls [Codex] #399, not additional implementation changes in this PR.
  • Prior P3 BOM correction remains present: TextDecoder("utf-8", { ignoreBOM: true }) and both-direction regression assertions. Independently compared the checker with Chromium: #caf%EF%BB%BF%C3%A9 targets id="caf&#xFEFF;é", but not plain id="café"; both agree.
  • Checker/docs/dependency files are unchanged since BOM-fix head 8c121955e29673554489d3498131342a8a58144f. All 35 checker/parser fixtures pass, including the earlier P2 srcset/entity/UTF-8/alias/CSS/base/artifact cases; the rebuilt 675-file site passes. No resurfaced P2 found in this supplemental check; this is not a claim of exhaustive browser/parser equivalence.

Checks and limitations

Validation used disposable archives/consumers of the exact head; the attached source worktree remains clean. Toolchain: Node 24.16.0 / npm 11.15.0 / ReScript 13.0.0-alpha.5 / Chromium 156.0.8078.4.

Passed: fresh npm ci (audit: 0 vulnerabilities); npm run test:negative (23 fixtures); WEBAPI_TEST_PORT=42984 npm run test:browser (includes clean/build of 385 modules; 4 tests); npm run build:docs; npm run check:docs-links (35 fixtures/675 files); npm run format:check; exact packed-consumer discrimination/positive/docs compilation probes; independent compiled-binding/BOM browser probes; npm ls entities; exact-base scope comparison and git diff --check. An initial docs-build attempt overlapped the browser command's compiler clean/build and failed reading compiler artifacts; rerunning after compilation completed passed. The 42984 browser invocation is an alternate-port run, not a claim that another port was tested.

Live exact-head checks: CI/build SUCCESS; Release/validate SUCCESS; deploy-docs and publish SKIPPED.

This supplemental pass did not rerun the full Node runtime, feature, full consumer, or release suites locally, nor the earlier exhaustive HTML-reference audit. No local Node 26, Firefox/WebKit/version matrix, external URL availability, live registry candidate installation, npm account settings, provenance publication, or release action was verified. Prior broader reviews remain separate evidence.

No repository source edits, merges, tags, publication, issue/settings changes, or formal review/approval were performed. This summary comment is the only GitHub write.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Final author verification update for PR #398 at head 6949c42cc17269575b9db4df08c6190bc0824ab8, based on #399 head 14f5873fc453e8d409244fd79a2afd71e9f25571. This supplements my earlier acceptance mapping; it is not a formal review approval or request to land.

Final local validation: npm run format:check; npm test; WEBAPI_TEST_PORT=4193 npm run test:browser (4 Chromium tests); npm run check:features (28 definitions); npm run test:negative (23 fixtures); npm run check:consumer (343-file tarball); npm run check:release; npm run build; npm run build:docs; npm run check:docs-links (35 fixtures); built artifact check (attribution present, no font binaries); npm ls entities --depth=0; and git diff --check. Fresh npm ci and npm audit (0 vulnerabilities) passed on this stack as well. Local Node was 24.16.0/npm 11.15.0; Node 26, Bun, external-link availability, other browser engines, and npm account settings/publication were not verified.

GitHub CI on this head: CI/build and Release/validate succeeded; deployment and publication were skipped. The independent supplemental review found no new blockers and confirmed that both string-stream negatives fail with the current API but compile against the former generic signature in a scratch consumer; see #398 (comment). That reviewer summary is not formal approval.

@jderochervlk

Copy link
Copy Markdown
Collaborator Author

Final stack synchronization for PR #398: the base now points to agent/alpha-binding-contracts at 0b4642539c9a41d9e2aa53c3278a9e6850d7a744; head is fd007c8d4a6d6ef9d1b6d4ebac4c7e26cc73ac11. The only inherited change since the previously verified head is the binding test’s middle-byte assertion. Docs, migration notes, checker, dependency, and workflow changes are unchanged; the diff still contains no binding/runtime implementation changes.

GitHub CI/build and Release/validate succeeded on this head; deployment and publication were skipped. Local full validation and the issue-by-issue author evidence remain recorded in #398 (comment). The supplemental docs review found no blockers; the final stack adds only the test assertion, not a new docs change. This is an author verification update, not a formal reviewer approval or request to merge.

@jderochervlk jderochervlk changed the title docs(webapi): document alpha and validate docs distribution [Codex] docs(webapi): update alpha guides and fix broken links [Codex] Nov 8, 2026
jderochervlk added a commit that referenced this pull request Nov 8, 2026
Fixes bindings that compiled but called the wrong browser method or used
the wrong types. This covers WebSocket and worker calls, observer
callbacks, and DOM, audio and crypto APIs.

Byte readers are now typed as `Uint8Array` rather than plain arrays.
HTTP body streams must yield `Uint8Array` chunks. Browser tests and
compiler checks cover the corrected behavior.

Builds on #397. Some public types change; #398 provides the migration
notes and remaining documentation.

Fixes #386. Fixes #389. Refs #383, #387, #388, #390, #391 and #392.
Base automatically changed from agent/alpha-binding-contracts to agent/alpha-tooling-release November 8, 2026 17:05
@jderochervlk
jderochervlk added this pull request to stack #401 November 8, 2026 17:06
jderochervlk added a commit that referenced this pull request Nov 8, 2026
Fixes bindings that compiled but called the wrong browser method or used
the wrong types. This covers WebSocket and worker calls, observer
callbacks, and DOM, audio and crypto APIs.

Byte readers are now typed as `Uint8Array` rather than plain arrays.
HTTP body streams must yield `Uint8Array` chunks. Browser tests and
compiler checks cover the corrected behavior.

Builds on #397. Some public types change; #398 provides the migration
notes and remaining documentation.

Fixes #386. Fixes #389. Refs #383, #387, #388, #390, #391 and #392.
@jderochervlk
jderochervlk force-pushed the agent/alpha-docs-distribution branch from fd007c8 to 7d92df2 Compare November 8, 2026 18:07
Base automatically changed from agent/alpha-tooling-release to main November 8, 2026 18:14
jderochervlk added a commit that referenced this pull request Nov 8, 2026
Makes the package installable with ReScript 13 alpha and checks the npm
package that consumers will actually install.

Improves the test runner, adds browser tests, and updates vulnerable
development dependencies. Alpha releases use numbered versions and are
checked before publishing. Pull request checks do not receive publishing
permissions.

This is the base for #399 and #398. A maintainer still needs to verify
npm Trusted Publishing before publishing the v1 alpha (#385).

Closes #384. Closes #396. Refs #383 and #385.
@jderochervlk
jderochervlk force-pushed the agent/alpha-docs-distribution branch from 7d92df2 to fa4931f Compare November 8, 2026 18:14
@jderochervlk
jderochervlk merged commit 844c32a into main Nov 8, 2026
4 checks passed
@jderochervlk
jderochervlk deleted the agent/alpha-docs-distribution branch November 8, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant