fix: skip cross-workspace channel collisions during bot sync - #130
Conversation
Slack Connect shared channels legitimately appear in multiple workspaces. Once one workspace records the channel, a later bot sync of another workspace hit the store's WorkspaceCollisionError and aborted the entire run. Demote the collision to a skip-with-warning at the API sync boundary, matching the desktop import path, and keep all other upsert errors fatal.
|
Codex review: found issues before merge. Reviewed August 6, 2026, 11:39 AM ET / 15:39 UTC. ClawSweeper reviewWhat this changesThe PR makes Slack bot sync warn and skip a channel already owned by another archived workspace, continues syncing other channels, adds regression coverage, and adds an unreleased changelog entry. Merge readinessKeep this collaborator-authored PR open for normal review. Current main still makes a cross-workspace channel collision fatal; the proposed API-boundary skip preserves the store invariant and matches the existing desktop-import precedent, but the release-owned changelog edit should be removed and the applicable policy requires current real-behavior proof before merge. Priority: P1 Review scores
Verification
How this fits togetherSlacrawl’s bot sync retrieves workspace channels, stores their metadata in the local archive, then fetches their messages. The archive store enforces a single workspace owner per channel; the sync layer determines whether that collision aborts the run or skips the affected channel. flowchart LR
A[Slack workspace channel list] --> B[Bot sync]
B --> C[Archive channel store]
C --> D{Owned by another workspace?}
D -->|No| E[Sync channel messages]
D -->|Yes| F[Warn and skip channel]
E --> G[Archived messages]
F --> G
Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Land the narrow API-boundary collision skip after recording a redacted real multi-workspace sync result, while retaining fatal handling for all non-collision store errors and leaving release-note ownership to the release process. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible with high confidence: seed a channel under one workspace, then sync a second workspace that exposes that channel; current main propagates the typed collision as a fatal error. Is this the best way to solve the issue? Yes for the functional change: handling only the typed channel collision at the API sync boundary preserves the store’s ownership protection and follows the existing desktop-import pattern. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4d3eadee7c07. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
…#131) Fifteen verified fixes from an autonomous triage + deep review: cross-workspace user/message collision skips completing #130, media MaxBytes overflow discarding attachments, symlinked-cache purge wedge, publish empty-manifest data loss, escaped-mention false positives, signal handling, tail error priority and repair resilience, --since RFC3339 contract, trends OOM cap, mcpclient/provider subprocess lifecycle, schema v7 thread/event indexes (measured >3000x on thread-root lookup), UTF-8-safe rendering, and single-owner consolidation of the tombstone SQL and media containment invariants. Details in PR body and review comment.
Problem
slacrawl sync(bot source) aborts the entire run as soon as it meets a channel that already belongs to a different workspace in the archive:Slack Connect shared channels legitimately surface in multiple workspaces. Whichever workspace records the channel first "owns" it in the single-workspace
channelstable, and every later sync of the other workspace then hitsWorkspaceCollisionErrorand dies — on a real 11-workspace archive this killed a 20,304-channel sync at channel 0.Fix
The store's collision guard stays intact — it's the right integrity check for message/batch writes, and the desktop import path (
redux.go) already skips the same collision class. This change demotes the collision only at the API sync boundary:syncChannelsWithSourcenow skips a channel owned by another workspace with a warning and continues, in both the serial and concurrent worker paths. Any other upsert error stays fatal.Test
TestSyncSkipsChannelOwnedByAnotherWorkspace: seeds the colliding channel under a different workspace, runs a full bot sync against the mock server, and asserts the sync succeeds, unaffected channels still sync, and the original workspace keeps ownership.make checkgreen (tidy/fmt/lint/test/smoke/snapshot).