LearnNewsExamplesServices
Frontmatter
title>-
authorneo-opus-ada
stateMerged
createdAtMay 30, 2026, 7:36 AM
updatedAtMay 30, 2026, 7:46 AM
closedAtMay 30, 2026, 7:46 AM
mergedAtMay 30, 2026, 7:46 AM
branchesdevfix/gh-syncer-bucketing-12188
urlhttps://github.com/neomjs/neo/pull/12192
Merged
neo-opus-ada
neo-opus-ada commented on May 30, 2026, 7:36 AM

Authored by Opus 4.8 (Claude Code). Session de8830c3-8d1b-47f8-90db-bd236c8b9bd2.

Resolves #12188 Resolves #12184 Related: #12186

Closed-item bucketing resolved closedAt → release over a sortedReleases list floored to syncStartDate (2025-01-01) and sorted ascending, so every pre-floor closed issue/PR collapsed into the oldest in-window release — a v8.1.0 catch-all holding 4,133 of 7,263 archived issues (56.9%). This fetches the full release history into the bucketing reference while keeping release-NOTES floored (the floor moves to syncNotes), so closed items bucket into the real release that shipped after they closed — with zero change to the on-disk notes set, its chunk layout, or the SSR route count. Separately, the milestone→version branch is now guarded by semver.valid, so descriptive milestones (#3286/#3287 carried titles like "neo.d.ts - Typescript definitions …") no longer become garbage version folders; they fall through to the same closedAt → release resolution.

FAIR-band: over-target — sole active implementer (@neo-gpt rate-limited, @neo-gemini benched per current project state) + operator-directed lane (epic #12186 P0).

Evidence: L1 (unit: full-history pagination, syncNotes floor, non-semver-milestone fall-through — 4 new tests, 206 green) → L2 required (AC: post-re-sync archive/issues/ has no v8.1.0 catch-all + no garbage folders). Residual: live re-sync + portal tickets-view verification [#12186].

Deltas from ticket (if any)

  • Release-notes stay floored; only bucketing goes full. sortedReleases (the bucketing reference) now spans the full history; this.releases is full too (so the fast-path cache reconstructs a full reference), but syncNotes floors writes to syncStartDate and indexes within the floored set. This keeps the portal Releases view + release-notes chunk layout byte-identical and avoids adding ~1,028 release SSR routes — a conscious scope boundary (full release-notes history is a separate, opt-in enhancement, not this fix).
  • maxReleases 1000 → 2000 (config.template) — the full history (~1,194 releases) exceeds the old cap; a cap below the total would silently drop the oldest releases. A loud WARN now fires if the cap is hit before history is exhausted (no silent truncation).
  • Updated one existing ReleaseNotesSyncer spec: its release dates were 2024 (pre-floor); with the floor now in syncNotes, in-window dates are required to exercise the "notes written" path. Production behavior is unchanged — fetchAndCacheReleases already filtered those pre-floor releases out before the fix, so they never reached disk.

Config template change (per mcp-config-template-change-guide)

  • Changed key: issueSync.maxReleases (1000 → 2000).
  • Local config.mjs follow-up (required): each clone's gitignored config.mjs overrides maxReleases independently — bump it to 2000 after merge so the full-history fetch isn't truncated. (Not committed; gitignored.)
  • Restart: unnecessary — the syncer reads config at run time; the next sync-github-workflow picks up the new value.
  • Peer notification: A2A sent (the change affects sync behavior in other clones).

Test Evidence

  • npm run test-unit -- test/playwright/unit/ai/services/github-workflow/206 passed (4 new, 0 regressions).
  • New tests:
    • ReleaseNotesSyncer.spec: cold full-history fetch (proves the early-exit and the filter were removed — pre-floor releases survive in sortedReleases, pagination does not stop at the floor); syncNotes floor (proves notes stay floored + index within the floored set while sortedReleases is full).
    • IssueSyncer.spec + PullRequestSyncer.spec: a non-semver milestone falls through to the closedAt → release fallback (v9.0.0), not a title-derived folder. Each fails without the guard.
  • node --check on all touched source files; pre-commit whitespace/shorthand hooks green.

Post-Merge Validation

  • Bump maxReleases to 2000 in each clone's local config.mjs.
  • Run a full sync-github-workflow re-sync; confirm resources/content/archive/issues/ has no v8.1.0 catch-all (pre-2025 issues distribute to their true releases) and no non-semver/garbage version folders.
  • Confirm portal News → Tickets shows clean release groups (no garbage groups sorted above the real versions).
  • Confirm release-notes chunk layout + releases.json are unchanged (notes still floored to syncStartDate).