LearnNewsExamplesServices
Frontmatter
id14484
titleRefine release-note orphan guard to its post-publish defect class
stateClosed
labels
bugaitesting
assigneesneo-opus-vega
createdAtJul 2, 2026, 5:05 PM
updatedAtJul 2, 2026, 5:40 PM
githubUrlhttps://github.com/neomjs/neo/issues/14484
authorneo-opus-vega
commentsCount0
parentIssue14483
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 2, 2026, 5:40 PM

Refine release-note orphan guard to its post-publish defect class

neo-opus-vega
neo-opus-vega commented on Jul 2, 2026, 5:05 PM

Context

Leaf of epic #14483. Operator verdict (2026-07-02): the flat-root release-notes staging file cannot be committed because a prior-session unit test forbids it — and the test, not the flow, is the defect. Live demonstration: PR #14480's first head (8cdc5d0b6, the v13.1.0 notes draft at the flat root) failed unit solely on this guard.

Sweep: epic-reshape execution under live operator direction; latest-20 live sweep 14:42Z + no competing claim on this surface (the guard was authored via #13273/#13276 and has no open follow-up).

The Problem

test/playwright/unit/ai/buildScripts/release/PublishReleaseNoteOrphan.spec.mjs (second test) asserts resources/content/release-notes/ contains zero flat v*.md files at all times. But the release pipeline's own contract requires exactly that file pre-cut: buildScripts/release/publish.mjs:83-87 pre-flight ERRORS unless resources/content/release-notes/v{version}.md exists; :161-173 appends the atomic-hash line to it on dev; :210 creates the GitHub Release from it; :223-226 removes it itself post-release. The guard outlaws the pipeline's mandatory staging state — the designed flow (v13.0 lineage: the flat file lived on dev through a month of refinement PRs, #12695→#12924) is unrepresentable under green CI.

The test's actual defect class (from #13273): a flat file lingering after publish, duplicating its chunk-N mirror and double-listing the version in the release index/sitemap.

The Architectural Reality

  • Guard: PublishReleaseNoteOrphan.spec.mjs — test 1 (publish.mjs cleanup-ordering source assertion) and test 3 (releases.json leaf uniqueness) are correct and stay.
  • Post-publish mirror: GH_SyncService.runFullSync() re-materializes the published release under resources/content/release-notes/chunk-N/ with frontmatter; _index.json maps version → chunk.
  • Known interplay (observation, NOT this leaf's scope): buildScripts/docs/index/release.mjs scans the directory recursively including flat files, so a committed pre-cut staging file surfaces the unreleased version in releases.json when the docs index regenerates. Recorded for the epic; whether the index builder should skip flat files is a separate editorial/product call.

The Fix

Narrow test 2 to the defect class: a flat v{X}.md fails the guard iff version X already exists in the chunked record (presence in _index.json keys or a chunk-*/v{X}.md file). A staging file for a not-yet-published version passes; a lingering post-publish duplicate still fails. No production code changes.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
PublishReleaseNoteOrphan.spec.mjs test 2 publish.mjs staging contract (:83-226) + #13273 defect class Orphan = flat file whose version is already chunk-mirrored Missing/unreadable _index.json → fall back to chunk-*/ directory scan Spec docblock updated to state the staging-window contract Spec green with a staging file present AND red with a simulated post-publish duplicate

Decision Record impact

none — test-scope refinement restoring an existing pipeline contract.

Acceptance Criteria

  • Test 2 passes with a flat v*.md whose version has no chunk mirror (the staging state)
  • Test 2 fails when a flat v*.md coexists with its chunk-N mirror (the #13273 orphan class) — proven via a temp-fixture case, not by committing a real orphan
  • Tests 1 and 3 unchanged
  • Spec docblock documents the staging-window lifecycle (exists pre-cut → publish consumes+removes → chunk mirror only)
  • PR Resolves this leaf and Refs #14483

Out of Scope

  • buildScripts/docs/index/release.mjs flat-file scan behavior (observation recorded above; separate call).
  • Any publish.mjs change.

Related

Related: #14483 (parent epic), #13273 / #13276 (guard origin), #14480 (the PR this unblocks)

Origin Session ID: 8cf234b7-e698-47ca-99e2-bf865196b6aa

Retrieval Hint: release-note orphan guard staging window flat root chunk mirror refinement

tobiu referenced in commit 72b1930 - "fix(release): scope orphan guard to post-publish duplicates (#14484) (#14487)" on Jul 2, 2026, 5:40 PM
tobiu closed this issue on Jul 2, 2026, 5:40 PM