Context
While recovering after context compaction and surveying the v13 release-note ingestion/SEO surface under #12696, I checked whether the v13 release note was visible in the portal release index and SEO outputs.
The v13 note is visible, but the check exposed a wider regression: the SEO generator currently only sees top-level release-note markdown files. Historical release notes now live under resources/content/release-notes/chunk-N/, so generated sitemap and llms.txt release-note sections contain only v13.0.0 while releases.json still contains the full historical set.
Live latest-open sweep: checked the latest 30 open issues on 2026-06-08; no equivalent open ticket found. Live duplicate searches for release notes sitemap chunked and llms release notes chunked returned no open issues. Exact local sweep found the closed prior sitemap contract #9592 and the closed release-index chunking repair #12176 / #11405, but no active ticket for the SEO collector regression. KB ticket sweep for release notes sitemap chunked collectReleaseRoutes SEO generator tickets #9592 #12176 surfaced #9592 as the closed source contract and no open duplicate.
The Problem
buildScripts/docs/seo/generate.mjs says it collects all release notes, but collectReleaseRoutes() uses a non-recursive glob:
buildScripts/docs/seo/generate.mjs:524-528 uses fg('resources/content/release-notes/*.md', ...).
- Current file-count probe:
resources/content/release-notes/**/*.md = 167 files; resources/content/release-notes/*.md = 1 file; 166 release notes are invisible to this collector.
apps/portal/sitemap.xml:1338 contains https://neomjs.com/news/releases/13.0.0, but the sitemap release route count is 1; it does not include 12.1.0, 11.13.0, or 8.13.0.
apps/portal/llms.txt:191-195 has a Release Notes section with only v13.0.0.
This contradicts the closed #9592 contract that release notes should be dynamically parsed into /news/releases/[version] sitemap URLs, and it regresses after release notes were chunked.
The Architectural Reality
The portal release navigation is already chunk-aware through a separate generator:
buildScripts/docs/index/release.mjs:44-62 explicitly documents recursive scanning of resources/content/release-notes including chunk-N/, then uses fg('**/*.md', { cwd: inputDir, absolute: true }).
apps/portal/resources/data/releases.json includes v13, 13.0.0, and historical chunked paths like resources/content/release-notes/chunk-2/v12.1.0.md.
The broken substrate is the SEO generator only. The fix should align collectReleaseRoutes() with the release-index generator instead of adding release-specific exceptions for v13.
The Fix
Update buildScripts/docs/seo/generate.mjs so collectReleaseRoutes() recursively scans release-note markdown files, derives the route version from the basename, and preserves the existing /news/releases/${version} route shape.
Regenerate and commit the SEO outputs that are source-controlled consumers of the generator:
apps/portal/sitemap.xml
apps/portal/llms.txt
Add or adjust focused test coverage for the recursive release-note collector if an existing SEO-generator test seam exists. If there is no existing test seam, add a minimal deterministic script-level test or document the verification commands in the PR body.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
collectReleaseRoutes() in buildScripts/docs/seo/generate.mjs |
#9592 plus buildScripts/docs/index/release.mjs recursive release-note ingestion |
Discover top-level and chunk-N/ release-note markdown files |
If no files exist, keep current empty release-route behavior |
Existing JSDoc should be corrected if needed |
Unit/script probe shows recursive count matches release-note markdown count |
apps/portal/sitemap.xml release-note URLs |
SEO generator output |
Include all release-note routes as /news/releases/[version] |
Existing sitemap lastmod fallback remains unchanged |
generated output |
Count includes 167 release routes; spot-check 13.0.0, 12.1.0, 11.13.0, 8.13.0 |
apps/portal/llms.txt Release Notes section |
SEO generator output |
Include all release-note raw links, not only top-level files |
Existing latest-updates section remains unchanged |
generated output |
Release Notes section includes historical chunked releases |
Decision Record impact
Aligned with ADR 0004 chunking behavior and the closed #9592 sitemap contract. No new ADR required.
Acceptance Criteria
Out of Scope
- Rewriting the v13 release-note prose.
- Changing the raw route serving contract.
- Reworking the release-note directory layout.
- Changing
seo.json; route-specific release-note metadata is not part of the current SEO service contract because nested release routes fall back to /news/releases.
Avoided Traps
- Do not special-case
v13.0.0; it only exposed the regression because it is the one top-level release note.
- Do not mutate
releases.json to solve this; it already recursively sees chunked notes.
- Do not broaden this into a general SEO overhaul. The release-blocking fix is the collector mismatch plus regenerated outputs.
Related
- Parent epic: #12696
- Prior closed sitemap contract: #9592
- Prior closed release-index chunking repair: #12176 / #11405
Origin Session ID: e8f07ef9-ef7e-4815-8ff4-7abe13720621
Handoff Retrieval Hints: release notes sitemap chunked collectReleaseRoutes, v13 release-note ingestion SEO survey, apps/portal/llms.txt Release Notes only v13
Context
While recovering after context compaction and surveying the v13 release-note ingestion/SEO surface under #12696, I checked whether the v13 release note was visible in the portal release index and SEO outputs.
The v13 note is visible, but the check exposed a wider regression: the SEO generator currently only sees top-level release-note markdown files. Historical release notes now live under
resources/content/release-notes/chunk-N/, so generated sitemap andllms.txtrelease-note sections contain onlyv13.0.0whilereleases.jsonstill contains the full historical set.Live latest-open sweep: checked the latest 30 open issues on 2026-06-08; no equivalent open ticket found. Live duplicate searches for
release notes sitemap chunkedandllms release notes chunkedreturned no open issues. Exact local sweep found the closed prior sitemap contract #9592 and the closed release-index chunking repair #12176 / #11405, but no active ticket for the SEO collector regression. KB ticket sweep forrelease notes sitemap chunked collectReleaseRoutes SEO generator tickets #9592 #12176surfaced #9592 as the closed source contract and no open duplicate.The Problem
buildScripts/docs/seo/generate.mjssays it collects all release notes, butcollectReleaseRoutes()uses a non-recursive glob:buildScripts/docs/seo/generate.mjs:524-528usesfg('resources/content/release-notes/*.md', ...).resources/content/release-notes/**/*.md= 167 files;resources/content/release-notes/*.md= 1 file; 166 release notes are invisible to this collector.apps/portal/sitemap.xml:1338containshttps://neomjs.com/news/releases/13.0.0, but the sitemap release route count is 1; it does not include12.1.0,11.13.0, or8.13.0.apps/portal/llms.txt:191-195has aRelease Notessection with onlyv13.0.0.This contradicts the closed #9592 contract that release notes should be dynamically parsed into
/news/releases/[version]sitemap URLs, and it regresses after release notes were chunked.The Architectural Reality
The portal release navigation is already chunk-aware through a separate generator:
buildScripts/docs/index/release.mjs:44-62explicitly documents recursive scanning ofresources/content/release-notesincludingchunk-N/, then usesfg('**/*.md', { cwd: inputDir, absolute: true }).apps/portal/resources/data/releases.jsonincludesv13,13.0.0, and historical chunked paths likeresources/content/release-notes/chunk-2/v12.1.0.md.The broken substrate is the SEO generator only. The fix should align
collectReleaseRoutes()with the release-index generator instead of adding release-specific exceptions for v13.The Fix
Update
buildScripts/docs/seo/generate.mjssocollectReleaseRoutes()recursively scans release-note markdown files, derives the route version from the basename, and preserves the existing/news/releases/${version}route shape.Regenerate and commit the SEO outputs that are source-controlled consumers of the generator:
apps/portal/sitemap.xmlapps/portal/llms.txtAdd or adjust focused test coverage for the recursive release-note collector if an existing SEO-generator test seam exists. If there is no existing test seam, add a minimal deterministic script-level test or document the verification commands in the PR body.
Contract Ledger Matrix
collectReleaseRoutes()inbuildScripts/docs/seo/generate.mjsbuildScripts/docs/index/release.mjsrecursive release-note ingestionchunk-N/release-note markdown filesapps/portal/sitemap.xmlrelease-note URLs/news/releases/[version]13.0.0,12.1.0,11.13.0,8.13.0apps/portal/llms.txtRelease Notes sectionDecision Record impact
Aligned with ADR 0004 chunking behavior and the closed #9592 sitemap contract. No new ADR required.
Acceptance Criteria
collectReleaseRoutes()recursively discoversresources/content/release-notes/**/*.mdwhile preserving route ids of the form/news/releases/${version}.apps/portal/sitemap.xmlincludes historical chunked release routes such as/news/releases/12.1.0,/news/releases/11.13.0, and/news/releases/8.13.0, plus/news/releases/13.0.0.apps/portal/llms.txtRelease Notessection includes historical chunked release raw links in addition to v13.apps/portal/resources/data/releases.jsonis already the correct shape for this issue.Out of Scope
seo.json; route-specific release-note metadata is not part of the current SEO service contract because nested release routes fall back to/news/releases.Avoided Traps
v13.0.0; it only exposed the regression because it is the one top-level release note.releases.jsonto solve this; it already recursively sees chunked notes.Related
Origin Session ID: e8f07ef9-ef7e-4815-8ff4-7abe13720621
Handoff Retrieval Hints:
release notes sitemap chunked collectReleaseRoutes,v13 release-note ingestion SEO survey,apps/portal/llms.txt Release Notes only v13