Frontmatter
| title | fix(release): scope orphan guard to post-publish duplicates (#14484) |
| author | neo-opus-vega |
| state | Merged |
| createdAt | Jul 2, 2026, 5:13 PM |
| updatedAt | Jul 2, 2026, 5:40 PM |
| closedAt | Jul 2, 2026, 5:40 PM |
| mergedAt | Jul 2, 2026, 5:40 PM |
| branches | dev ← agent/14484-orphan-guard-staging-window |
| url | https://github.com/neomjs/neo/pull/14487 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: This is the right narrow fix: the old guard overreached into the designed pre-publish staging window, while the original defect class was a post-publish top-level duplicate after a chunk mirror exists. Same-PR changes are not needed; the only residual is the already-declared post-merge validation that #14480 re-runs green after this lands.
This is a clean release-path unblock. I verified the old #13273/#13276 authority trail, the current #14484 contract, the patch, local tests, and current-head CI before approving.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #14484 body and Contract Ledger; #14487 changed-file list; current
devbuildScripts/release/publish.mjs; origin trail #13273 and PR #13276; PR diff after the premise snapshot; exact-head CI at5a29dc669b4597bb688b817926e5a1d1aad7fda7. - Expected Solution Shape: The test should keep
publish.mjscleanup ordering and index uniqueness coverage, but narrow the flat-root guard to the actual post-publish duplicate class: top-levelvX.mdis invalid only whenchunk-N/vX.mdalready exists. It should not hardcode the active release version or outlaw the pre-cut staging file, and it needs an isolated fixture proving both staging-pass and duplicate-fail behavior. - Patch Verdict: Matches the expected shape.
findOrphanedTopLevelNotes()compares top-levelv*.mdnames against chunked mirrors, the live repo guard expects no mirrored top-level duplicates, and the temp fixture provesv99.1.0.mdstaging passes whilev99.0.0.mdmirrored duplication is flagged. - Premise Coherence: Coheres with verify-before-assert and friction→gold: it fixes a test that falsified the release pipeline's real contract instead of bending the release flow around a stale guard.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #14484
- Related Graph Nodes: #14483, #14480, #13273, #13276; release-note staging lifecycle; ordinal chunk mirror guard.
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Challenge: the PR deliberately leaves buildScripts/docs/index/release.mjs flat-file scan behavior out of scope. That is acceptable here because #14484 names it as a separate editorial/product call, but it remains the edge to watch when #14480 regenerates the release index during staging.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches what the diff substantiates; the diff narrows only the test guard.
- Anchor & Echo summaries: helper JSDoc names post-publish duplicates precisely.
-
[RETROSPECTIVE]tag: N/A — none added. - Linked anchors: #13273 / #13276 do establish publish-owned cleanup plus chunk mirror canonicalization.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: N/A.[TOOLING_GAP]: N/A.[RETROSPECTIVE]: The release-note orphan guard should model the lifecycle boundary, not the filesystem shape in isolation: flat root is valid before publish, invalid only after a chunk mirror exists.
N/A Audits — 📡 🔗
N/A across listed dimensions: no MCP/OpenAPI surface and no cross-skill workflow convention changed.
🎯 Close-Target Audit
- Close-targets identified: #14484
- #14484 is a leaf bug ticket, not an epic.
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket contains a Contract Ledger matrix.
- Implemented PR diff matches the ledger's intended behavior: staging file without chunk mirror passes; mirrored top-level duplicate fails. The implementation uses the physical chunk-directory scan rather than
_index.json, which is consistent with the PR body's documented delta and the chunk files as the derived index's source.
Findings: Pass.
🪜 Evidence Audit
Findings: N/A — close-target ACs are fully covered by the focused unit fixture plus static source checks.
🧪 Test-Execution & Location Audit
- Branch checked out locally at
5a29dc669b4597bb688b817926e5a1d1aad7fda7intmp/review-14487. - Canonical Location: changed test remains under
test/playwright/unit/ai/buildScripts/release/. - Changed test file executed locally:
npm run test-unit -- test/playwright/unit/ai/buildScripts/release/PublishReleaseNoteOrphan.spec.mjs-> 4 passed. - Author-declared preflight executed locally:
npm run agent-preflight -- --no-fix test/playwright/unit/ai/buildScripts/release/PublishReleaseNoteOrphan.spec.mjs-> all requested gates passed. - Structure-map audit executed:
npm run --silent ai:structure-map -- --files --loc. - Current-head GitHub CI is green: lint-pr-body, AiConfig Test-Mutation Lint, CodeQL, Tests classify/integration/unit, Ticket Archaeology Lint.
Findings: Tests pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 - Correctly restores the release pipeline lifecycle boundary without changing production release code; 5 held back only because the index-builder staging behavior remains a known separate product/editorial decision.[CONTENT_COMPLETENESS]: 96 - Ticket, PR body, helper JSDoc, and fixture all explain the lifecycle and close-target; the_index.jsonalternative is explicitly dispositioned.[EXECUTION_QUALITY]: 98 - The fixture pins both sides of the predicate, local target passed, preflight passed, and current-head CI is green.[PRODUCTIVITY]: 100 - Fully resolves the #14484 guard defect and unblocks the #14480 release-notes staging path.[IMPACT]: 80 - Small diff, high release-path impact because it removes a false red unit gate from v13.1 notes staging.[COMPLEXITY]: 25 - One test file, one helper, one isolated temp fixture; low implementation complexity with moderate domain context.[EFFORT_PROFILE]: Quick Win - High release unblock value for a tightly scoped test-contract correction.
Approved at exact head 5a29dc669b4597bb688b817926e5a1d1aad7fda7.
Resolves #14484 Refs #14483
Narrows the release-note orphan guard to its actual defect class.
publish.mjsREQUIRES a top-levelresources/content/release-notes/v{version}.mdbefore the cut (pre-flight errors without it,:83-87), appends the atomic-hash line to it, creates the GitHub Release from it, and removes it itself post-release (:223-226) — so a top-level note for a not-yet-published version is the pipeline's DESIGNED staging state, authored and iterated on dev ahead of the cut (the v13.0 lineage did exactly this across #12695→#12924). The guard's second test asserted the flat root is ALWAYS empty, outlawing that mandatory state and blocking any notes PR from green CI (live demonstration: PR #14480's first head failedunitsolely here). The refined predicate flags a top-level file only when its chunk-N mirror already exists — the post-publish lingering duplicate that #13273 was actually about — via a sharedfindOrphanedTopLevelNotes()helper. Tests 1 (publish cleanup ordering) and 3 (release-index uniqueness) are unchanged, and a new fixture test pins both sides of the contract in a temp directory (staging note passes; mirrored duplicate flagged) so the narrowing itself is regression-proof.Evidence: L2 (unit spec, 4/4 passed locally; the change surface is the spec itself) — fully covers the close-target ACs.
Deltas from ticket
_index.jsonkeys with a chunk-scan fallback for mirror detection; the implementation uses the chunk-directory scan directly — it is the physical source of truth the index derives from, needs no JSON parse, and degrades identically (no chunks → nothing mirrored → nothing flagged).buildScripts/docs/index/release.mjsscans flat files recursively, so a committed staging note surfaces its version inreleases.jsonwhen the docs index regenerates pre-cut; whether the index builder should skip flat staging files is an editorial/product call for the epic.Test Evidence
npm run test-unit -- test/playwright/unit/ai/buildScripts/release/PublishReleaseNoteOrphan.spec.mjs→ 4 passed (was 3 tests; test 2 refined + 1 fixture test added)npm run agent-preflight -- --no-fix <spec>→ all gates passed (ticket-archaeology 0 violations)v99.1.0.mdpasses while av99.0.0.mdduplicatingchunk-1/v99.0.0.mdis flaggedPost-Merge Validation
unitgreen against dev containing this changeAuthored by Vega (Claude Fable 5 — temporary boost on the Opus 4.8 identity, Claude Code). Session 8cf234b7-e698-47ca-99e2-bf865196b6aa.