Skip to content

fix: fence org lifecycle status and lease writes - #2317

Merged
Makisuo merged 12 commits into
mainfrom
fix/org-lifecycle-races
Nov 6, 2026
Merged

Makisuo merged 12 commits into
mainfrom
fix/org-lifecycle-races

Merge remote-tracking branch 'origin/main' into HEAD

c4edac2
Select commit
Loading
Failed to load commit list.
Maple Review Bot / Maple / review succeeded Nov 6, 2026 in 3m 0s

Confidence 10/10 · No issues found

🟢 Confidence 10/10 · safe to merge. Every fence and lease is pinned by a PGlite test at the state boundary it guards, and nothing outside those writes changed.
no findings · tests covered · risk high · 4/4 new units observable

Each lifecycle write now states the state it expects: schema apply fences on its run id, post-merge settle on its lease, reward finalize on its reservation, repo sync status on an active repo in the prior state. All paths are pinned by PGlite tests. The open VcsQueueError/GithubAppError reports are untouched.

  • Schema apply progress, stamp and failure writes fence on the claimed workflow_instance_id, with a 5-minute heartbeat
  • updateRepoSyncStatus requires an active repo in one of the caller's expected sync states
  • finalizeRewardClaim/releaseRewardClaim clear only the reservation they took
  • Post-merge settle requires waiting plus the examination's lease

Before merge

  • Manual · Expect a schema apply in flight at deploy time to fail on its payload; the org re-applies after the 30-minute stale window

Production impact

Open errors in the changed files (3)
Issue Service Occurrences File
@maple/backend/vcs/GithubAppError (4 issues) maple-chat 75 packages/backend/src/services/integrations/vcs/VcsRepository.ts
@maple/http/errors/VcsProviderError (2 issues) maple-chat 9 packages/backend/src/services/integrations/vcs/VcsRepository.ts
@maple/http/errors/VcsQueueError (2 issues) maple-api 6 packages/backend/src/services/integrations/vcs/VcsSyncService.ts

After this merges, Maple checks whether they stop.

Production traffic of the changed files (last 7 days)
File Calls/day Busiest operations
packages/backend/src/services/integrations/vcs/VcsRepository.ts 9.6k VcsRepository.updateRepoSyncStatus 9.6k/day, 0.0% err
packages/backend/src/services/pr-review/PrReviewPostMergeService.ts 1.1k PrReviewPostMergeService.examine 1.1k/day, 0.0% err
What was checked
  • failAbandonedScans filters org, repo, running and a stale started_at; the scanner test proves a fresh scan survives
  • Walked the sync state machine: only a repo still backfilling can be written ready, so a real resync still stamps lastSyncedAt
  • reserveRewardClaim writes and returns the same now, so whileReserved matches the lease it handed out
Observability coverage: 4 of 4 changes observable
Change Kind Observable Evidence
ClickHouse schema apply run (workflow steps + heartbeat) background workflow yes maple-schema-apply telemetry in ClickHouseSchemaApplyWorkflow.ts:24; updateRun/withRunHeartbeat are Effect.fn spans
VcsRepository.updateRepoSyncStatus guarded write db write yes Effect.fn("VcsRepository.updateRepoSyncStatus")
DependencyScanStore.failAbandonedScans db write yes Effect.fn("DependencyScanStore.failAbandonedScans") inside the scanner's scan span
Onboarding reward reserve/finalize/release db write yes Effect.fn("OnboardingService.reserveRewardClaim") and siblings

c4edac2 · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.