---
number: 12178
title: 'fix(docs): release index recursive scan for chunk-N release-notes (#12176)'
author: neo-opus-ada
state: MERGED
createdAt: '2026-05-29T18:52:46Z'
updatedAt: '2026-05-29T20:01:07Z'
closedAt: '2026-05-29T20:01:03Z'
mergedAt: '2026-05-29T20:01:03Z'
head: claude/silly-goldberg-5aa653
base: dev
url: 'https://github.com/neomjs/neo/pull/12178'
---
Authored by Claude Opus 4.8 (Claude Code), operating as the @neo-opus-ada swarm identity. Session: worktree `claude/silly-goldberg-5aa653`.

FAIR-band: over-target [22/30] — taking this lane under operator-direction (tobiu directed the neo-first ADR-0004 Phase-2 fix this session).

Resolves #12176

The release-notes index generator `release.mjs` was never migrated to the chunk-N release-notes shape that `ReleaseNotesSyncer` (#11405) produces — its sibling `tickets.mjs` was migrated in #11287/#11295 but the release index was out of that scope. It globbed `*.md` non-recursively (matching zero files once release-notes moved under `chunk-N/`) and emitted flat, reconstructed paths. Result: the committed `releases.json` paths now 404 (e.g. `v12.1.0.md` lives at `chunk-2/`), and any regeneration would silently empty the index. This switches to a recursive glob + `path.relative` (mirroring `tickets.mjs:130`) and commits the corrected `releases.json`.

Evidence: L2 (ran `create-release-index` — 166 release paths, all resolve to on-disk files; recursive scan confirmed finding chunk-1 + chunk-2) → L2 required (close-target ACs are index-correctness + path-resolution, fully tool-verifiable). Portal view is path-agnostic (`await fetch(path)`, proven by the already-working tickets view), so no runtime-only residual. No residuals.

## Deltas from ticket

- Fixed a pre-existing `date: date` verbose-key form at `release.mjs:100` (surfaced by the `check-shorthand` pre-commit hook, which scans the whole staged file) → ES2015 shorthand. Mechanical, in-file, required to commit the touched file.

## Test Evidence

- `node buildScripts/docs/index/release.mjs` → `Found 166 releases.` (was **0** with the non-recursive glob).
- Path-resolution check over the generated `releases.json`: `leaf entries=166  missing=0  parents=5` — every emitted path resolves to a real file on disk.
- Spot-check: `v12.1.0` → `resources/content/release-notes/chunk-2/v12.1.0.md` (exists; previously the flat path `release-notes/v12.1.0.md` 404'd).
- Major-version tree grouping + descending-semver sort preserved (v12 expanded first, 5 parent nodes).
- `git diff --check` clean; `check-whitespace` + `check-shorthand` pre-commit hooks pass.
- No existing spec for `buildScripts/docs/index/*` generators (consistent with the repo convention — these are verified by running, same as `tickets.mjs`).

## Post-Merge Validation

- [ ] Portal release-notes view renders and content loads for a recent release (e.g. v12.1.0) on the deployed portal — symmetric with the already-working tickets view; index correctness is verified pre-merge.

## Related

- Parent epic: #11372 (ADR 0004 — Universal Ordinal-100 Content Architecture), Phase 2
- Sibling consumer migration (tickets): #11287, #11295
- Release-notes chunking that surfaced the gap: #11405
- Sibling cleanup ticket (separate PR, unassigned): #12177
- Authority: `learn/agentos/decisions/0004-github-content-architecture.md` §2.1, §9 item 11
