LearnNewsExamplesServices
Frontmatter
id13002
titlePer-sync archival moves never prune emptied active chunk folders
stateClosed
labels
bugaibuild
assigneesneo-gpt
createdAtJun 12, 2026, 3:58 PM
updatedAtJun 12, 2026, 9:22 PM
githubUrlhttps://github.com/neomjs/neo/issues/13002
authorneo-fable-clio
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[x] 13001 Release archival maroons merged PRs: milestone-gated, but PRs carry no milestones
closedAtJun 12, 2026, 9:22 PM

Per-sync archival moves never prune emptied active chunk folders

neo-fable-clio
neo-fable-clio commented on Jun 12, 2026, 3:58 PM

Context

Operator-reported during the v13.0.0 release thread: after the release archival moved 1,715 closed issues out of active resources/content/issues/, the working tree where the pipeline runs is littered with empty chunk folders (git cannot represent empty dirs, so the litter is invisible in fresh clones but accumulates on the pipeline runner / operator checkout — and risks confusing chunk-numbering or directory-walking tooling that globs dirs rather than files).

Release classification: post-release hygiene.

The Problem

The recursive empty-dir pruner already existsIssueSyncer.mjs:1206-1224 ("Recursively removes now-empty directories under root (after a re-bucket relocation leaves source chunk/version folders empty). Children are pruned before parents; root is never removed.") — but it is invoked only on the re-bucket migration path (the #12194 one-time relocation). The regular per-sync archival move (closed item relocates active → version bucket) never calls it, so any chunk whose last file departs stays behind as an empty dir.

The Architectural Reality

  • The pruner: ai/services/github-workflow/sync/IssueSyncer.mjs:1206-1224 (children-before-parents, root-preserved — exactly the right primitive).
  • The archival move paths in IssueSyncer / PullRequestSyncer / DiscussionSyncer relocate files without the post-move prune.
  • Empirical state: the operator's checkout shows "lots of empty folders" under resources/content/issues post-v13; my fresh clone shows zero (git clones cannot materialize them) — confirming the litter is working-tree residue of the mover, not repo state.

The Fix

Invoke the existing pruner (or its extracted shared form) after each sync run's archival relocations, across all three syncers — scoped to the active content roots the run actually moved files out of. Idempotent, cheap (readdir per touched dir), and already children-before-parents safe.

Acceptance Criteria

  • A sync run that archives the last file out of an active chunk leaves no empty dir behind (all three syncers).
  • The pruner remains root-preserving (active roots themselves never removed).
  • One-time cleanup of the currently littered dirs on the pipeline runner (a single prune invocation over the active roots).

Out of Scope

  • The milestone-gating archival gap (sibling ticket #13001) and the #12186-family historical bucketing.

Related

#13001 (sibling, same surface), #12194 (where the pruner was born), #11486 (prior archival-anomaly WARN noise).

Live latest-open sweep: checked latest 12 open issues at 2026-06-12T13:40Z + #12996/#12999/#13001 known; no equivalent found. A2A in-flight sweep: clean.

Origin Session ID: 3e1566f6-6336-4db4-8726-189004578d8b

Retrieval Hint: "empty chunk folders archival prune per-sync rmdir children before parents"

tobiu referenced in commit 9e995dc - "fix(github-workflow): prune emptied sync chunk dirs (#13002) (#13009)" on Jun 12, 2026, 9:22 PM
tobiu closed this issue on Jun 12, 2026, 9:22 PM