Context
Sub of #12186 (full root-cause analysis + investigation provenance there). The portal tickets view buckets 4,133 of 7,263 archived issues (56.9%) into v8.1.0 — a catch-all dump, not a real per-release distribution.
Root cause (grounded against IssueSyncer.mjs:367-369 + ReleaseNotesSyncer.mjs:117-157)
Closed issues with no milestone and no valid oldVersion are bucketed via:
const release = (ReleaseNotesSyncer.sortedReleases || []).find(r => new Date(r.publishedAt) > closed);
sortedReleases is filtered to publishedAt >= syncStartDate (= 2025-01-01) and sorted ascending. For any pre-2025 closed issue, the oldest in-window release (v8.1.0) is the first to satisfy publishedAt > closedAt, so .find() returns it. The true bucket — a pre-floor release — was never a candidate. (No hidden default is involved; :378 correctly routes genuine no-matches to active/Backlog.)
The Fix
Make the bucketing reference list (ReleaseNotesSyncer.sortedReleases, as consumed by issue/PR/Discussion bucketing) contain the full release history rather than only >= syncStartDate. Precedent: IssueSyncer.mjs:528-532 already overrides syncStartDate with a 2017-01-01 clean-slate floor for issue fetching — releases need the symmetric treatment. Cost is trivial (~24 GraphQL pages @ ~1pt for ~1,194 releases). One-time re-sort of release-notes chunks is a regeneratable-cache rebuild (ADR-0004 §1.3/§3.6); release-notes have no archive tier (§2.1), so this is not a sealed-chunk violation.
Lands with #12184 (milestone semver-guard) — see #12184 for the necessary-but-insufficient coupling.
Acceptance Criteria
Out of Scope
- The milestone→version semver guard itself (#12184 — lands together).
- PR/Discussion delta-fetch + query-cost (rate-limit hardening) — #12186 P1.
Related
- #12186 (epic), #12184 (milestone guard — lands together).
- Authority:
learn/agentos/decisions/0004-github-content-architecture.md.
Retrieval Hint: grep sortedReleases + syncStartDate in ai/services/github-workflow/sync/.
Context
Sub of #12186 (full root-cause analysis + investigation provenance there). The portal tickets view buckets 4,133 of 7,263 archived issues (56.9%) into v8.1.0 — a catch-all dump, not a real per-release distribution.
Root cause (grounded against
IssueSyncer.mjs:367-369+ReleaseNotesSyncer.mjs:117-157)Closed issues with no milestone and no valid
oldVersionare bucketed via:const release = (ReleaseNotesSyncer.sortedReleases || []).find(r => new Date(r.publishedAt) > closed);sortedReleasesis filtered topublishedAt >= syncStartDate(= 2025-01-01) and sorted ascending. For any pre-2025 closed issue, the oldest in-window release (v8.1.0) is the first to satisfypublishedAt > closedAt, so.find()returns it. The true bucket — a pre-floor release — was never a candidate. (No hidden default is involved;:378correctly routes genuine no-matches to active/Backlog.)The Fix
Make the bucketing reference list (
ReleaseNotesSyncer.sortedReleases, as consumed by issue/PR/Discussion bucketing) contain the full release history rather than only>= syncStartDate. Precedent:IssueSyncer.mjs:528-532already overridessyncStartDatewith a2017-01-01clean-slate floor for issue fetching — releases need the symmetric treatment. Cost is trivial (~24 GraphQL pages @ ~1pt for ~1,194 releases). One-time re-sort of release-notes chunks is a regeneratable-cache rebuild (ADR-0004 §1.3/§3.6); release-notes have no archive tier (§2.1), so this is not a sealed-chunk violation.Lands with #12184 (milestone semver-guard) — see #12184 for the necessary-but-insufficient coupling.
Acceptance Criteria
>= syncStartDate.archive/issues/has no v8.1.0 catch-all; pre-2025 closed issues distribute to the release that shipped after they closed.syncStartDatefloor's other consumers before widening it globally — if the floor also bounds what release-notes content is written to disk (vs. only the in-memory bucketing reference), scope the change to the bucketing consumer or consciously accept the wider fetch. (shared-default cross-consumer caution.)Out of Scope
Related
learn/agentos/decisions/0004-github-content-architecture.md.Retrieval Hint: grep
sortedReleases+syncStartDateinai/services/github-workflow/sync/.