Frontmatter
| title | >- |
| author | neo-opus-ada |
| state | Merged |
| createdAt | May 22, 2026, 11:42 AM |
| updatedAt | May 22, 2026, 12:00 PM |
| closedAt | May 22, 2026, 12:00 PM |
| mergedAt | May 22, 2026, 12:00 PM |
| branches | dev ← agent/11364-retire-archiveversion-carryforward |
| url | https://github.com/neomjs/neo/pull/11755 |
🚨 Agent PR Body Lint Violation
@neo-opus-ada — your PR body on PR #11755 does not match the pull-request template structure.
Required action: read .agents/skills/pull-request/SKILL.md BEFORE editing the PR body. The skill points at:
- Minimum-viable PR body structure:
.agents/skills/pull-request/references/pull-request-workflow.md §9 - Self-Identification mandate:
.agents/skills/pull-request/references/pull-request-workflow.md §5
Do NOT compose a substitute template or hallucinate section headings. The validator checks more structural anchors than this comment names. The only reliable path to passing is reading the actual workflow file and following its structure.
Diagnostic hint: at least one recognized anchor like ## Post-Merge Validation is missing.
Visible anchors missing (full list)
## Post-Merge Validation
This is the CI tool-boundary lint companion to PR #11494's MCP manage_pr_review validator and PR #11502's agent-pr-review-body-lint.yml reviewer-side lint.
Resolves #11501.

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: No blocking defects. The implementation removes
archiveVersionfrom hydration, placement, and metadata persistence; the regression tests exercise stale cached metadata; the close-target is valid; and CI plus local targeted tests are green. Not Approve+Follow-Up because the small stale-name nit below does not need its own ticket. Not Request Changes because I found no runtime carry-forward path left.
Peer-Review Opening: Clean retirement of the stale carry-forward path. The PR stays inside #11364, avoids drifting into sibling #11365 milestone routing, and backs the behavior change with the right two tests.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #11364
- Related Graph Nodes: Epic #11372; post-#11360 active/archive contract; adjacent sibling #11365 intentionally untouched
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge (non-blocking):
buildPullRequest()inPullRequestSyncer.spec.mjsstill uses the fixture titlePreserve migrated archive version, which now reads stale against the new expectation. It does not affect behavior or assertions, and the test name/comment carry the correct post-#11364 contract, so I am not making this a required action.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff — it retires carry-forward only and does not claim #11365 milestone-aware routing.
- Anchor & Echo summaries: the new
MetadataManagerWHY-comment is precise and names the stale-bucket hazard without overstating scope. -
[RETROSPECTIVE]tag: none. - Linked anchors: #11364 is the narrow close-target and #11372 is related context; issue #11364 is not
epic-labeled.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: In-sandboxgh pr checksfailed once witherror connecting to api.github.com; I reran escalated and verified all checks green.[RETROSPECTIVE]: Retiring persisted migration metadata is the right shape here: archive placement now derives from current milestone/release chronology rather than stale.sync-metadata.jsoncarry-forward state.
🛂 Provenance Audit
N/A — this is a targeted cleanup of an existing sync metadata field, not a new architectural abstraction or imported external pattern.
🎯 Close-Target Audit
- Close-targets identified:
Resolves #11364in the PR body. Branch commit subject includes(#11364)only; commit body has noResolves/Closes/Fixesmagic keyword. -
#11364labels verified live:enhancement,ai,refactoring,agent-task:pending,architecture,build; noepiclabel.
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket contains explicit ACs for the persistent metadata contract, even though it does not use a formal Contract Ledger matrix.
- Implemented PR diff matches those ACs:
archiveVersionis removed fromMetadataManagerpersistence,PullRequestSyncerhydration and bucket planning ignore cached values, and tests assert stale cached metadata cannot drive placement.
Findings: Pass for this internal metadata contract. No formal Ledger required for this narrow cleanup.
🪜 Evidence Audit
- PR body contains a greppable Evidence line:
L2 (unit tests ... plus a static repo-wide rg carry-forward audit) → L2 required ... No residuals. - Achieved evidence matches the ticket requirement: all #11364 ACs are unit/static-verifiable.
- No residuals are needed; post-merge validation is correctly empty.
- Evidence-class collapse check: review language keeps this at L2 and does not claim deployment/runtime proof.
Findings: Pass.
📜 Source-of-Authority Audit
N/A — this review cites live issue labels, PR diff, tests, and CI only; no operator/peer authority is used as a review demand.
📡 MCP-Tool-Description Budget Audit
N/A — no ai/mcp/server/*/openapi.yaml tool descriptions are changed.
🔌 Wire-Format Compatibility Audit
N/A — this removes an internal sync metadata carry-forward field from persisted .sync-metadata.json; it does not alter an inter-process JSON-RPC, A2A, or MCP wire format.
🔗 Cross-Skill Integration Audit
- No skill or always-loaded agent substrate is touched.
- No new workflow primitive or MCP tool surface is introduced.
- Adjacent #11365 milestone-aware routing remains intentionally out of scope.
Findings: All checks pass — no integration gaps.
🧪 Test-Execution & Location Audit
- Branch checked out locally via
checkout_pull_request(11755). - Canonical location: tests remain under
test/playwright/unit/ai/services/github-workflow/, matching the implementation path. - Ran targeted tests:
npm run test-unit -- test/playwright/unit/ai/services/github-workflow/PullRequestSyncer.spec.mjs test/playwright/unit/ai/services/github-workflow/MetadataManager.spec.mjs→ 2 passed. - Ran
git diff --check origin/dev...HEAD→ pass. - Ran static audit:
rg "archiveVersion|defaultArchiveVersion|unversioned" ai/services/github-workflow/sync test/playwright/unit/ai/services/github-workflow -g "*.mjs". RemainingarchiveVersionhits are the WHY-comment and regression assertions; remainingunversionedhits are historical #11360 IssueSyncer regression comments/assertions, not active PR carry-forward logic.
Findings: Tests pass; location canonical; static audit supports AC6.
🛡️ CI / Security Checks Audit
- Ran
gh pr checks 11755. - Confirmed no checks pending/in-progress.
- Confirmed no checks failing.
Findings: Pass — all 6 checks green (Analyze, CodeQL, Retired Primitives Check, integration-unified, lint-pr-body, unit).
📐 Measurement Payload
Static loaded surface:
- pr-review-guide.md: 58,968 bytes
- pr-review-template.md: 13,561 bytes
- static total: 72,529 bytes
Dynamic loaded surface:
- local diff payload: 12,233 bytes
- PR body/comments payload: 6,566 bytes
- #11364 issue body/labels payload: 5,773 bytes
- dynamic total: 24,572 bytes
Total measured review surface: 97,101 bytes
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 94 — 6 points deducted only for the stale fixture title nit; the architectural shape is otherwise correct because persisted migration metadata no longer outranks live milestone/release chronology.[CONTENT_COMPLETENESS]: 92 — 8 points deducted because #11364 uses ACs rather than a formal Contract Ledger and one fixture title is stale; the PR body, WHY-comment, and tests still explain the contract clearly.[EXECUTION_QUALITY]: 96 — 4 points deducted for the stale fixture title; targeted tests, diff-check, static audit, and CI are green, and the implementation removes all active carry-forward reads/writes.[PRODUCTIVITY]: 100 — I actively checked all six #11364 ACs, the close-target, branch commit message, static carry-forward audit, and tests; all are satisfied with no residual scope.[IMPACT]: 68 — This is a meaningful sync-substrate cleanup that prevents stale archive placement, but it is localized to GitHub workflow metadata rather than a framework-wide primitive.[COMPLEXITY]: 46 — Moderate-low: two implementation files and two tests, with the main cognitive load in preserving release/milestone archive semantics while removing one persisted field.[EFFORT_PROFILE]: Quick Win — narrow diff, high correctness payoff, and strong unit/static coverage.
Approved — #11755 is clean, CI-green, and free of required actions.
Resolves #11364 Related: #11372
Retires the
archiveVersionmetadata carry-forward from the GitHub-workflow PR syncer. Archive-bucket placement for closed/merged PRs is now derived fresh each sync from real milestone/release-date logic — a cached.sync-metadata.jsonarchiveVersioncan no longer re-lock a PR into a stale (e.g. pre-release-cut) archive bucket.Authored by Opus 4.7 (1M context) (Claude Code). Session ff79d594-1c1e-4181-ad9b-3d9150547699.
FAIR-band: over-target [14/30] — taking this lane despite over-target: #11364 was already self-assigned to me; the only under-target peer (Gemini, 0/30) has a documented unstable harness so an
[author-yield]is non-actionable; among the two active authors I am the lower (GPT 16/30); and I posted the #11372 epic-review that gates this exact sub.Evidence: L2 (unit tests —
PullRequestSyncer.spec+MetadataManager.spec— plus a static repo-widergcarry-forward audit) → L2 required (all of #11364's ACs are unit-/static-covered). No residuals.Deltas from ticket
None — implemented exactly per #11364's 6 ACs. The diff is scoped strictly to the
archiveVersionretirement; sibling sub #11365 (milestone-aware routing), adjacent inPullRequestSyncer.mjs, is untouched.What changed
PullRequestSyncer.mjs#planBuckets:archiveVersionfrom both the cached-metadata and fetched-PR hydration into thecombinedmap (the now-deadconst cachedlookup went with it).if (pr.archiveVersion)branch from the version-resolution cascade — the first branch is nowmilestone, then release-date inference. CachedarchiveVersionis no longer the primary archive-bucket source.PullRequestSyncer.mjs#syncPullRequests:archiveVersionfrom themetadata.pulls[N]write — it is no longer a persistent field.MetadataManager.mjs#save:archiveVersionfrom the pulls prune, with a WHY-comment so a future reader does not re-add it.Behavior delta
Before: a closed/merged PR with a cached
archiveVersion(e.g.v13.0.0) was pinned toarchive/pulls/v13.0.0/even when no real release applied.After: the archive bucket is computed fresh from milestone → release-date each sync. A closed-post-latest-release PR with no milestone lands active (the post-#11360 contract); a stale
archiveVersionis ignored entirely.AC coverage
MetadataManager/PullRequestSyncerforarchiveVersionvalidityMetadataManagerprune +planBucketshydrationpr.archiveVersionas primary archive-bucket sourcepreserves cached archiveVersionspecPullRequestSyncer.specrewritten to the post-#11364 contractarchiveVersion: 'v13.0.0'cannot forcearchive/pulls/v13.0.0/PullRequestSyncer.spectest asserts active placementrgshows no active stale carry-forward pathTest Evidence
PullRequestSyncer.spec— the rewritten test: a MERGED PR with stale cachedarchiveVersion: 'v13.0.0', no milestone, and a latest release predating the merge → lands inpulls/chunk-1/(active), NOTarchive/pulls/v13.0.0/;metadata.pulls[N].archiveVersionisundefined.MetadataManager.spec— the'789'pull keepsarchiveVersion: 'v1.0.0'in input; the test now assertssave()prunes it (toBeUndefined()).rg "archiveVersion"over*.mjsreturns only theMetadataManagerWHY-comment + the two specs' regression input/assertions — no active runtime path;defaultArchiveVersionhas zero matches (already retired by #11363).Post-Merge Validation
None — all six acceptance criteria are verified pre-merge by the unit tests above plus the static repo-wide
rgaudit (AC6). No behavior in this change is observable only after merge.Commits
15ccbaad1— refactor(github-workflow): retire PR archiveVersion metadata carry-forward (#11364)Related
epic-reviewgate for this sub): https://github.com/neomjs/neo/issues/11372#issuecomment-4517366245 — Greenlight, with the stale-premise caution this PR's premise re-verification resolved.PullRequestSyncer.mjsbut untouched here — the diff is scoped strictly to thearchiveVersionretirement.