Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace (Grace). Operator prio-0 (broken neomjs.com/news portal).
Context
neomjs.com/news/pulls (and tickets) list wrong PR/issue numbers. The chunk folders should be exactly 100 items (ADR 0004 Universal Ordinal-100; folder labels are position-ranges 1-100, 101-200…), but on-disk active chunks are 148/135/180/100/75 — non-uniform, with overlapping/gapped ranges (e.g. resources/content/pulls/chunk-1 holds 148 PRs spanning 9537-12693). This is in the neo repo content directly; the pages deploy just mirrors it.
Root Cause (V-B-A: ADR 0004 §2.2, contentPath.mjs, PullRequestSyncer.mjs, IssueSyncer.mjs, pulls.mjs)
Ordinal-100 chunking is position-dependent: a item's chunk = Math.floor(rank/100)+1 where rank is its position among all active items sorted ascending by id. But the syncers only ever rank/re-place the delta:
- Stale-rank drift (pulls + issues):
syncPullRequests/pullFromGitHub call #planBuckets(metadata, <delta-fetch>) and only relocate the delta items. When a release is cut and a batch is archived, the active set shrinks → every surviving active item's rank shifts → its correct chunk changes — but only delta items move; the rest stay in stale folders. reconcileClosed*Locations relocates terminal items to archive but nothing re-ranks the remaining active tier.
- Pulls worse (asymmetry):
PullRequestSyncer:492 does metadata.pulls = {} (delta-rebuilt, "not a full index" per its own JSDoc), vs IssueSyncer:601 issues: {...metadata.issues} (cumulative). So even delta pulls' itemIndex is computed over a partial set.
The index generators (pulls.mjs/tickets.mjs) faithfully mirror the on-disk folders (getSourceBucket → dirname); they're not independently buggy. contentPath.mjs's floor(itemIndex/100)+1 math is correct. The fix is in the placement.
The Fix
- Add a full-corpus active-tier re-chunk pass: scan all active
pr-*.md/issue-*.md/discussion-*.md, sort ascending by id, recompute chunk-N via contentPath, fs.rename any mis-located file, prune empty dirs. This is the active-tier sibling of reconcileClosed*Locations (which only archives). Idempotent (no-op when already ordinal-correct).
- Wire it into the sync/rebuild pipeline (
rebuildContentIndexesAndSeo.mjs before the index generators) so it runs every sync → no re-drift.
- Fix the
metadata.pulls = {} vs {...metadata.issues} asymmetry.
- Regenerate the current content + indexes to un-break the portal now.
Acceptance Criteria
Out of Scope
- Archive-tier chunks (sealed per ADR 0004 §2.6 — immutable, do not re-chunk).
Related
- ADR 0004 (
learn/agentos/decisions/0004-github-content-architecture.md), contentPath.mjs, the github-workflow syncers, buildScripts/docs/index/*.mjs.
Release classification: prio-0 operator-flagged (public portal correctness); boardless (no portal board).
Origin Session ID: 0f5d9f1d-0683-452d-aac1-f467297186ac
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace (Grace). Operator prio-0 (broken neomjs.com/news portal).
Context
neomjs.com/news/pulls(and tickets) list wrong PR/issue numbers. The chunk folders should be exactly 100 items (ADR 0004 Universal Ordinal-100; folder labels are position-ranges 1-100, 101-200…), but on-disk active chunks are 148/135/180/100/75 — non-uniform, with overlapping/gapped ranges (e.g.resources/content/pulls/chunk-1holds 148 PRs spanning 9537-12693). This is in the neo repo content directly; the pages deploy just mirrors it.Root Cause (V-B-A: ADR 0004 §2.2,
contentPath.mjs,PullRequestSyncer.mjs,IssueSyncer.mjs,pulls.mjs)Ordinal-100 chunking is position-dependent: a item's chunk =
Math.floor(rank/100)+1whererankis its position among all active items sorted ascending by id. But the syncers only ever rank/re-place the delta:syncPullRequests/pullFromGitHubcall#planBuckets(metadata, <delta-fetch>)and only relocate the delta items. When a release is cut and a batch is archived, the active set shrinks → every surviving active item's rank shifts → its correct chunk changes — but only delta items move; the rest stay in stale folders.reconcileClosed*Locationsrelocates terminal items to archive but nothing re-ranks the remaining active tier.PullRequestSyncer:492doesmetadata.pulls = {}(delta-rebuilt, "not a full index" per its own JSDoc), vsIssueSyncer:601issues: {...metadata.issues}(cumulative). So even delta pulls'itemIndexis computed over a partial set.The index generators (
pulls.mjs/tickets.mjs) faithfully mirror the on-disk folders (getSourceBucket → dirname); they're not independently buggy.contentPath.mjs'sfloor(itemIndex/100)+1math is correct. The fix is in the placement.The Fix
pr-*.md/issue-*.md/discussion-*.md, sort ascending by id, recomputechunk-NviacontentPath,fs.renameany mis-located file, prune empty dirs. This is the active-tier sibling ofreconcileClosed*Locations(which only archives). Idempotent (no-op when already ordinal-correct).rebuildContentIndexesAndSeo.mjsbefore the index generators) so it runs every sync → no re-drift.metadata.pulls = {}vs{...metadata.issues}asymmetry.Acceptance Criteria
Latestlist shows the newest PRs/issues first, with contiguous position labels (1-100, 101-200, …).Out of Scope
Related
learn/agentos/decisions/0004-github-content-architecture.md),contentPath.mjs, the github-workflow syncers,buildScripts/docs/index/*.mjs.Release classification: prio-0 operator-flagged (public portal correctness); boardless (no portal board).
Origin Session ID: 0f5d9f1d-0683-452d-aac1-f467297186ac