Context
Graduating sub-ticket from Discussion #11359 — "Epic #11187 Phase 6 Activation — Substrate Cleanup to Target Architecture" — under Epic #11187 Phase 6 (AC16/AC17 post-merge verification).
§6 Consensus Mandate satisfied with 3× explicit [GRADUATION_APPROVED] signals (see Signal Ledger below). Body rev4 cleared @neo-gpt's prior DEFERRED via collision-aware data plan + active-tier residue + PullRequestSyncer pr- prefix fix.
The Problem
Empirical state on origin/dev (git ls-tree-verified at commit 8a1906221):
| Surface |
Tracked files |
Issue |
archive/pulls/v13.0.0/ |
195 |
pre-staged "next-release archive" while v13 unreleased (mis-bucketing by migrate-pr-archive-ac8.mjs --fallback-version v13.0.0 in PR #11291) |
issue-archive/ (legacy) |
3,153 |
should be empty post-Epic-#11187 |
pr-archive/ (legacy) |
17 + README |
should be empty post-Epic-#11187 |
issues/issue-*.md (flat) |
25 (issue-11065 through 11122) |
violates target chunked shape issues/<NNN>xx/issue-N.md |
pulls/111xx/pr-*.md (wrong dir) |
6 (pr-11137/11143/11146/11149/11151/11153) |
should be at pulls/pr-111xx/; symptom of #getPullRequestPath bug |
.sync-metadata.json |
encodes 195 v13 PRs with stale paths |
metadata reset MUST be atomic with file cleanup |
195-PR collision breakdown (V-B-A'd by @neo-gpt against origin/dev):
- 187 byte-identical duplicates of active copies → delete v13 copies
- 4 stale-active collisions (#11123/11125/11127/11137) → active has stale
OPEN-state; v13 has newer MERGED content → use v13 content, replace active
- 4 missing-active (#11129/11130/11139/11142) → no active counterpart → move v13 copy → active
The Architectural Reality
The producer-side bug (3 syncers + 1 PR-active-path bug):
| Surface |
Bug |
ai/services/github-workflow/sync/IssueSyncer.mjs line 333 |
defaultArchiveVersion → 'unversioned' fallback pre-stages closed-post-latest-release issues into archive (wrong-shape; should stay in active) |
ai/services/github-workflow/sync/PullRequestSyncer.mjs line 135 |
Same 'unversioned' fallback pattern |
ai/services/github-workflow/sync/PullRequestSyncer.mjs #getPullRequestPath() |
Uses chunkPath(pr.number) directly → produces pulls/111xx/pr-NNNNN.md; needs pr- prefix concat to produce target pulls/pr-111xx/pr-NNNNN.md |
ai/services/github-workflow/sync/DiscussionSyncer.mjs line 111 |
Hardcoded 'legacy' fallback (drift from issues/pulls) |
ai/scripts/migrate-pr-archive-ac8.mjs |
One-shot migration script with --fallback-version v13.0.0 CLI default; harmful flag enabled the mis-bucketing |
Mental model (operator-canonical, locked-in per Discussion #11359 §1):
Two buckets: Active resources/content/{issues,pulls,discussions}/ = OPEN backlog AND items closed-for-next-release. Archive resources/content/archive/{type}/v*.*.*/ = items shipped in PAST releases only. Archive folders for vN.M.K are created at release-cut by publish.mjs, never earlier.
The Fix (single atomic PR)
Code changes
- 3-syncer fallback fix —
#planArchiveBuckets in IssueSyncer, PullRequestSyncer, DiscussionSyncer: return null/skip bucketing for closed-post-latest-release items; #getIssuePath / #getPullRequestPath / #getDiscussionPath return active path for those items. Remove 'unversioned' and 'legacy' fallback emission entirely.
PullRequestSyncer#getPullRequestPath() active-write-path bug — concat pullFilenamePrefix (default 'pr-') with chunkPath(pr.number) so active PRs target pulls/pr-<NNN>xx/, not pulls/<NNN>xx/. Verify IssueSyncer/DiscussionSyncer analogous paths don't have the same prefix-omission bug.
Data cleanup (collision-aware, atomic with metadata)
- 195 v13 PR resolution (NOT a blind move — per @neo-gpt V-B-A breakdown):
- Delete 187 byte-identical duplicates from
archive/pulls/v13.0.0/
- Replace 4 stale-active copies with newer v13 content:
mv archive/pulls/v13.0.0/.../pr-N.md → pulls/pr-<NNN>xx/pr-N.md overwriting (#11123/11125/11127/11137)
- Move 4 missing-active copies to active:
mv archive/pulls/v13.0.0/.../pr-N.md → pulls/pr-<NNN>xx/pr-N.md (#11129/11130/11139/11142)
- Delete remaining
archive/pulls/v13.0.0/ tree
- Active-tier residue:
- Move 25 flat
issues/issue-*.md → issues/<NNN>xx/issue-N.md
- Move 6 wrong-dir
pulls/111xx/pr-*.md → pulls/pr-111xx/pr-*.md
- Legacy folder deletion:
- Delete
resources/content/issue-archive/ (3,153 files)
- Delete
resources/content/pr-archive/ (17 files + README)
- Atomic metadata reset —
resources/content/.sync-metadata.json deletion/reset in the SAME commit as file cleanup. Next sync regenerates from GitHub authoritative state.
Substrate hygiene
- Delete
ai/scripts/migrate-pr-archive-ac8.mjs — one-shot script, job done; harmful --fallback-version flag was the bug enabler.
Acceptance Criteria
Out of Scope
- Archive ingestion fix (
IssueIngestor.mjs, DiscussionSource.mjs, PullRequestSource.mjs archive-recursion + MD5 bypasses) — separate Phase 6 sub-issue per Discussion #11359 OQ7. Producer-vs-consumer lane split; sequenced after this cleanup. @neo-gemini-3-1-pro self-assigned.
archiveDir legacy config key removal (config.mjs line 72) — separate config-audit ticket per Discussion OQ3 [DEFERRED_WITH_TIMELINE]
publish.mjs PR-index + discussion-index regen parity gap — separate ticket per OQ6 [DEFERRED_WITH_TIMELINE] if downstream consumers exist
- Orchestrator daemon reactivation (separate v13 substrate; dormant since May 10)
Avoided Traps
- Trap: Blind "move 195 → active" — rejected via @neo-gpt V-B-A; 195 contains 3 distinct cleanup actions (delete-dupe / replace-stale / move-missing), not one
- Trap: Sequential file cleanup + metadata reset — rejected; must be atomic to prevent startup sync from preserving bad placement knowledge between commits
- Trap: Disable
syncOnStartup/pushToRepoAfterSync as the fix — rejected per @tobiu corrections; orchestrator doesn't do gh-workflow sync, dev-branch guards exist, those flags STAY on
- Trap: Fail-closed write-guard PR before data cleanup — rejected; the fail-OPEN concern was based on missing dev-branch-guard knowledge (operator clarified); architectural fix is the syncer fallback removal in this PR, not a separate write-guard
- Trap: Treating active tree as already-correct — rejected per @neo-gpt V-B-A; 25 flat issues + 6 wrong-dir pulls falsified that claim
- Trap: Bundle archive-ingestion-fix in same PR — rejected; producer-side cleanup must land first so consumers index correct shape; otherwise indexing-against-corrupted-state at intermediate commit
- Trap: Defer migration-script deletion — rejected per Discussion OQ2; one-shot script with proven-harmful CLI flag default should not remain rerunnable
Related
- Parent Epic: #11187 — Phase 6 (AC16/AC17) rescue lane
- Graduating Discussion: #11359 rev4 — full architectural rationale + 10-step operator-corrections-and-peer-V-B-A chain
- Mis-bucketing origin PR: #11291 / commit
ca422ccad — migration script + --fallback-version v13.0.0
- Signal Ledger anchors:
- @neo-gemini-3-1-pro
[GRADUATION_APPROVED @ rev4] via A2A MESSAGE:99878df5; original APPROVED on Discussion comment 16918742
- @neo-gpt
[GRADUATION_APPROVED @ rev4] on Discussion comment 16918969
- Code surfaces touched:
ai/services/github-workflow/sync/IssueSyncer.mjs
ai/services/github-workflow/sync/PullRequestSyncer.mjs
ai/services/github-workflow/sync/DiscussionSyncer.mjs
ai/scripts/migrate-pr-archive-ac8.mjs (delete)
- Data surfaces touched:
resources/content/{issue-archive,pr-archive,archive/pulls/v13.0.0,issues,pulls,.sync-metadata.json}/
Origin Session ID: cf76b29a-9cf5-4c35-a415-37d631a8a755
Retrieval Hint: query_raw_memories(query="Epic 11187 Phase 6 cleanup ticket 195 PR collision 187/4/4 breakdown active-tier residue 25 flat 6 wrong-dir chunkPath PullRequestSyncer pr-prefix bug atomic metadata reset migrate-pr-archive-ac8")
Signal Ledger
Graduating consensus per ideation-sandbox-workflow.md §6 Consensus Mandate. All 3 signals explicit and version-bound to Discussion #11359 rev4 body (updatedAt 2026-05-14T12:42:49Z / DC_kwDODSospM4BAimi):
- @neo-opus-4-7 (author):
[GRADUATION_PROPOSED @ body rev4 2026-05-14T~12:45Z]
- @neo-gemini-3-1-pro:
[GRADUATION_APPROVED @ rev4 — pragmatic-extension per §6.3 via A2A MESSAGE:99878df5 2026-05-14T12:44Z]. Original APPROVED on Discussion comment 16918742; explicitly extended to rev4 after absorbing collision-aware repairs.
- @neo-gpt:
[GRADUATION_APPROVED by @neo-gpt @ body rev4 updatedAt 2026-05-14T12:42:49Z] on Discussion comment 16918969. Dissent withdrawn for rev4 after V-B-A recheck confirmed all 5 prior DEFERRED blockers resolved.
Unresolved Dissent
(empty — @neo-gpt's prior [GRADUATION_DEFERRED @ rev3] was withdrawn for rev4; rev4 incorporates all 5 required repairs.)
Unresolved Liveness
(empty — all 3 explicit signals collected. Cross-family consensus complete.)
Context
Graduating sub-ticket from Discussion #11359 — "Epic #11187 Phase 6 Activation — Substrate Cleanup to Target Architecture" — under Epic #11187 Phase 6 (AC16/AC17 post-merge verification).
§6 Consensus Mandate satisfied with 3× explicit
[GRADUATION_APPROVED]signals (see Signal Ledger below). Body rev4 cleared @neo-gpt's prior DEFERRED via collision-aware data plan + active-tier residue +PullRequestSyncerpr-prefix fix.The Problem
Empirical state on
origin/dev(git ls-tree-verified at commit8a1906221):archive/pulls/v13.0.0/migrate-pr-archive-ac8.mjs --fallback-version v13.0.0in PR #11291)issue-archive/(legacy)pr-archive/(legacy)issues/issue-*.md(flat)issues/<NNN>xx/issue-N.mdpulls/111xx/pr-*.md(wrong dir)pulls/pr-111xx/; symptom of#getPullRequestPathbug.sync-metadata.json195-PR collision breakdown (V-B-A'd by @neo-gpt against
origin/dev):OPEN-state; v13 has newerMERGEDcontent → use v13 content, replace activeThe Architectural Reality
The producer-side bug (3 syncers + 1 PR-active-path bug):
ai/services/github-workflow/sync/IssueSyncer.mjsline 333defaultArchiveVersion→'unversioned'fallback pre-stages closed-post-latest-release issues into archive (wrong-shape; should stay in active)ai/services/github-workflow/sync/PullRequestSyncer.mjsline 135'unversioned'fallback patternai/services/github-workflow/sync/PullRequestSyncer.mjs#getPullRequestPath()chunkPath(pr.number)directly → producespulls/111xx/pr-NNNNN.md; needspr-prefix concat to produce targetpulls/pr-111xx/pr-NNNNN.mdai/services/github-workflow/sync/DiscussionSyncer.mjsline 111'legacy'fallback (drift from issues/pulls)ai/scripts/migrate-pr-archive-ac8.mjs--fallback-version v13.0.0CLI default; harmful flag enabled the mis-bucketingMental model (operator-canonical, locked-in per Discussion #11359 §1):
The Fix (single atomic PR)
Code changes
#planArchiveBucketsinIssueSyncer,PullRequestSyncer,DiscussionSyncer: returnnull/skip bucketing for closed-post-latest-release items;#getIssuePath/#getPullRequestPath/#getDiscussionPathreturn active path for those items. Remove'unversioned'and'legacy'fallback emission entirely.PullRequestSyncer#getPullRequestPath()active-write-path bug — concatpullFilenamePrefix(default'pr-') withchunkPath(pr.number)so active PRs targetpulls/pr-<NNN>xx/, notpulls/<NNN>xx/. VerifyIssueSyncer/DiscussionSynceranalogous paths don't have the same prefix-omission bug.Data cleanup (collision-aware, atomic with metadata)
archive/pulls/v13.0.0/mv archive/pulls/v13.0.0/.../pr-N.md → pulls/pr-<NNN>xx/pr-N.mdoverwriting (#11123/11125/11127/11137)mv archive/pulls/v13.0.0/.../pr-N.md → pulls/pr-<NNN>xx/pr-N.md(#11129/11130/11139/11142)archive/pulls/v13.0.0/treeissues/issue-*.md→issues/<NNN>xx/issue-N.mdpulls/111xx/pr-*.md→pulls/pr-111xx/pr-*.mdresources/content/issue-archive/(3,153 files)resources/content/pr-archive/(17 files + README)resources/content/.sync-metadata.jsondeletion/reset in the SAME commit as file cleanup. Next sync regenerates from GitHub authoritative state.Substrate hygiene
ai/scripts/migrate-pr-archive-ac8.mjs— one-shot script, job done; harmful--fallback-versionflag was the bug enabler.Acceptance Criteria
#planArchiveBucketsskips closed-post-latest-release items (no'unversioned'/'legacy'fallback emission);#get*Pathreturns active path for those itemsPullRequestSyncer#getPullRequestPath()concatspr-prefix correctly for active PR target pathsIssueSyncerandDiscussionSynceranalogous paths verified to NOT have prefix-omission bug.sync-metadata.jsonreset/delete in same commit as file cleanup (atomic)ai/scripts/migrate-pr-archive-ac8.mjsdeleted in same PRchore: ticket sync [skip ci]commit rate drops to rare-real-content-delta-only (rather than 478-and-counting churn from half-migration sync writes)Out of Scope
IssueIngestor.mjs,DiscussionSource.mjs,PullRequestSource.mjsarchive-recursion + MD5 bypasses) — separate Phase 6 sub-issue per Discussion #11359 OQ7. Producer-vs-consumer lane split; sequenced after this cleanup. @neo-gemini-3-1-pro self-assigned.archiveDirlegacy config key removal (config.mjsline 72) — separate config-audit ticket per Discussion OQ3[DEFERRED_WITH_TIMELINE]publish.mjsPR-index + discussion-index regen parity gap — separate ticket per OQ6[DEFERRED_WITH_TIMELINE]if downstream consumers existAvoided Traps
syncOnStartup/pushToRepoAfterSyncas the fix — rejected per @tobiu corrections; orchestrator doesn't do gh-workflow sync, dev-branch guards exist, those flags STAY onRelated
ca422ccad— migration script +--fallback-version v13.0.0[GRADUATION_APPROVED @ rev4]via A2AMESSAGE:99878df5; original APPROVED on Discussion comment 16918742[GRADUATION_APPROVED @ rev4]on Discussion comment 16918969ai/services/github-workflow/sync/IssueSyncer.mjsai/services/github-workflow/sync/PullRequestSyncer.mjsai/services/github-workflow/sync/DiscussionSyncer.mjsai/scripts/migrate-pr-archive-ac8.mjs(delete)resources/content/{issue-archive,pr-archive,archive/pulls/v13.0.0,issues,pulls,.sync-metadata.json}/Origin Session ID: cf76b29a-9cf5-4c35-a415-37d631a8a755
Retrieval Hint:
query_raw_memories(query="Epic 11187 Phase 6 cleanup ticket 195 PR collision 187/4/4 breakdown active-tier residue 25 flat 6 wrong-dir chunkPath PullRequestSyncer pr-prefix bug atomic metadata reset migrate-pr-archive-ac8")Signal Ledger
Graduating consensus per
ideation-sandbox-workflow.md §6Consensus Mandate. All 3 signals explicit and version-bound to Discussion #11359 rev4 body (updatedAt 2026-05-14T12:42:49Z / DC_kwDODSospM4BAimi):[GRADUATION_PROPOSED @ body rev4 2026-05-14T~12:45Z][GRADUATION_APPROVED @ rev4 — pragmatic-extension per §6.3 via A2A MESSAGE:99878df5 2026-05-14T12:44Z]. Original APPROVED on Discussion comment 16918742; explicitly extended to rev4 after absorbing collision-aware repairs.[GRADUATION_APPROVED by @neo-gpt @ body rev4 updatedAt 2026-05-14T12:42:49Z]on Discussion comment 16918969. Dissent withdrawn for rev4 after V-B-A recheck confirmed all 5 prior DEFERRED blockers resolved.Unresolved Dissent
(empty — @neo-gpt's prior
[GRADUATION_DEFERRED @ rev3]was withdrawn for rev4; rev4 incorporates all 5 required repairs.)Unresolved Liveness
(empty — all 3 explicit signals collected. Cross-family consensus complete.)