Skip to content

Release: v0.10.2 - #254

Merged
themightychris merged 19 commits into
mainfrom
develop
Oct 15, 2026
Merged

themightychris merged 19 commits into
mainfrom
develop

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Technical

themightychris and others added 17 commits October 15, 2026 15:29
gitsheets#301 shipped repo.sync() and repo.isAncestor in 2.8.0 and
develop already runs ^2.9.0, so the external block is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
…anism

Mechanism-only wording: reconcile moves from hand-rolled git plumbing
to gitsheets' sync primitive, and the hot-reload pre-check to
repo.isAncestor. Outcomes, conflict-branch naming and the single
write-lock critical section for ref move + rebuild are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Swap reconcile.ts's hand-rolled merge-base / merge-tree / commit-tree /
update-ref / push plumbing for repo.sync({ onConflict:
'preserve-branch' }), and the webhook's rev-parse + merge-base
pre-check for repo.isAncestor. Outcome vocabulary and webhook response
are unchanged: gitsheets' 'ahead' maps to 'pushed-ahead' and the
conflict branch keeps the conflicts/<UTC> name.

repo.sync() takes its handle's write lock and throws lock_held inside
withLock, but the hot reload needs ref move + store refresh + rebuild
in one critical section, or a write queued on the lock can run in the
gap, validate against pre-reload in-memory state and clobber what the
reload brought in. So the serving repository's withLock still wraps
the whole reconcile, and sync runs through a short-lived side handle
on the same gitdir whose own lock is uncontended. The fetch stays a
separate lock-free step (sync can't fetch without locking).

A new test holds the lock, queues the reload and then a write behind
it, and asserts the ref doesn't move until the lock frees and no
commit lands before the rebuild; it fails for both sync-then-lock
variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
A staff spam vote only deactivated; deleting took a pipeline run or a
Purge click per account. A daily in-process sweep now purges everyone
whose human votes are all spam, the newest three or more days old, in
one commit, and the roster shows when each will go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGqwPjt3v4eMfiHpPmCKnR
Members whose human votes are all spam, still deactivated and not
staff, are purged by a daily in-process sweep three days after the
newest vote: all of them in one cfp-api commit listing the slugs, with
the projects only they touched. The purge cascade moved into
purgePeople() so the Purge button and the sweep share it. Roster rows
carry purgeAfter, shown as a "Purges {date}" chip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGqwPjt3v4eMfiHpPmCKnR
Plan the follow-up to gitsheets-scripts now that gitsheets 2.9 ships
ref-pinned sheets (#303) and public raw-file writes plus orphan and
branch-creating transactions (#305).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
… transact

gitsheets 2.9 ships ref-pinned read-only sheets (#303) and lets
transact({ parent, branch }) create a missing branch (#305). Read
person-evaluations through openSheet(name, { ref }) instead of a no-op
transaction, and parent a fresh clone's first prune on origin/<branch>
so gitsheets creates the local branch, dropping the create-only
update-ref.

A dry-run or no-op run on a fresh clone no longer creates the local
branch; it appears only when a prune commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
…transact

Read the previous snapshot's ids through openStore(repo, { ref }) (#303)
rather than a no-op transaction, and on first run parent the snapshot on
origin/<branch> or the initial parent so transact({ parent, branch })
creates legacy-import (#305). The create-only update-ref is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Replace writeConfigRootCommit's hash-object / temp index / write-tree /
commit-tree plumbing with one orphan transact({ parent: null }) that
stages the source's .gitsheets/ files with tx.writeFile (gitsheets
2.9, #305).

The final snapshot commit stays on raw commit-tree + update-ref:
2.9's tx.sheet() loads configs from the transaction's parent (HEAD for
an orphan), never from files staged with tx.writeFile in the same
transaction. So records can't be upserted straight into an orphan, and
gitsheets can't point a branch at an existing commit. Each remaining
raw call is commented with its reason.

Tests now pin the snapshot shape: a parentless commit carrying the
source's configs and contracts byte-for-byte plus records, HEAD on the
snapshot branch, the tag, a no-op same-seed re-run, and no refs after
a failed verification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Records that scrub-data's single-transaction snapshot isn't reachable
on gitsheets 2.9 (tx.sheet() can't see configs staged with
tx.writeFile), lists every remaining raw git call in apps/api/scripts
with its reason, and files the upstream gap plus the two backfill
scripts as follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
The intro still said "the next pipeline run removes them"; a spam vote
now leads to a purge three days later unless someone disagrees.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGqwPjt3v4eMfiHpPmCKnR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGqwPjt3v4eMfiHpPmCKnR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Q2tgjZEUrtvVk6k8SpdXJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGqwPjt3v4eMfiHpPmCKnR
refactor(api): reconcile through gitsheets repo.sync()
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Author

Changelog

- refactor(api): reconcile through gitsheets repo.sync() [#251] @themightychris
- refactor(scripts): read pinned sheets and create branches through gitsheets [#252] @themightychris
- feat: daily scheduled purge of spam-voted accounts [#253] @themightychris

refactor(scripts): read pinned sheets and create branches through gitsheets
feat: daily scheduled purge of spam-voted accounts
@themightychris
themightychris merged commit 334067e into main Oct 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant