The R2 secrets were configured on this repository on 2026-09-13 and the first
configured run is green: run 34765639736
reports R2: synced 10912 object(s), deleted 0; daily tarball written for 2026-09-13.
The mirror works. Its prefix is one segment deeper than this workflow's own
comment says it is, and that gap is only visible from the bucket side.
What the comment promises vs. what is in the bucket
.github/workflows/board-snapshot.yml documents the mirror as objectstack/board/….
An independent S3 ListObjectsV2 against the bucket (not the run log) returns:
objectstack/board/board/manifest.json
objectstack/board/board/comments/…
objectstack/board/board/issues/…
objectstack/board/board/reviews/…
objectstack/snapshots/2026-09-13.tar.gz
board/board/. 10912 of the 10913 objects sit under it.
Cause
Two lines that are each correct alone:
- the snapshot writes into
archive/board (SNAPSHOT_ARGS: --out=archive/board)
- the sync source is the worktree ROOT (
aws s3 sync archive/ "$mirror", with
mirror="s3://${R2_BUCKET}/objectstack/board/")
So archive/board/X maps to objectstack/board/ + board/X.
Why it is worth fixing even though nothing reads the archive
Nothing does read it — that invariant is stated in the file and still holds. The
cost is paid exactly once, in the situation the whole workflow exists for: a
restore driven from the documented path looks in objectstack/board/ and finds
one directory instead of a manifest. The daily tarball is unaffected (it is
written to its own key from -C archive ., so it carries ./board/… and is
self-describing).
Fix
Either spelling works; the first keeps the documented layout:
aws s3 sync archive/board/ "$mirror" …
Note that the migration needs no cleanup step: with --delete, the stale
objectstack/board/board/ tree is inside the new sync target and has no local
counterpart, so the first run after the change removes it. That is also the
reason not to fix it by widening the target to objectstack/ instead — that
spelling puts objectstack/snapshots/ inside a --delete target and would
eat the daily tarballs, which is the failure the existing comment already
warns about.
Found while configuring the four R2 secrets; no code change made.
The R2 secrets were configured on this repository on 2026-09-13 and the first
configured run is green: run 34765639736
reports
R2: synced 10912 object(s), deleted 0; daily tarball written for 2026-09-13.The mirror works. Its prefix is one segment deeper than this workflow's own
comment says it is, and that gap is only visible from the bucket side.
What the comment promises vs. what is in the bucket
.github/workflows/board-snapshot.ymldocuments the mirror asobjectstack/board/….An independent S3
ListObjectsV2against the bucket (not the run log) returns:board/board/. 10912 of the 10913 objects sit under it.Cause
Two lines that are each correct alone:
archive/board(SNAPSHOT_ARGS: --out=archive/board)aws s3 sync archive/ "$mirror", withmirror="s3://${R2_BUCKET}/objectstack/board/")So
archive/board/Xmaps toobjectstack/board/+board/X.Why it is worth fixing even though nothing reads the archive
Nothing does read it — that invariant is stated in the file and still holds. The
cost is paid exactly once, in the situation the whole workflow exists for: a
restore driven from the documented path looks in
objectstack/board/and findsone directory instead of a manifest. The daily tarball is unaffected (it is
written to its own key from
-C archive ., so it carries./board/…and isself-describing).
Fix
Either spelling works; the first keeps the documented layout:
Note that the migration needs no cleanup step: with
--delete, the staleobjectstack/board/board/tree is inside the new sync target and has no localcounterpart, so the first run after the change removes it. That is also the
reason not to fix it by widening the target to
objectstack/instead — thatspelling puts
objectstack/snapshots/inside a--deletetarget and wouldeat the daily tarballs, which is the failure the existing comment already
warns about.
Found while configuring the four R2 secrets; no code change made.