CedarCopilot wants to merge 0 commits into staging from fix/sherlock-slack-list-channels-pagination-20260817-205526
Live on prod, no production signal yet
OTEL fallback found no prod spans matching listSlackChannels / Slack conversations.list since deploy.
OTEL fallback found no prod spans matching listSlackChannels / Slack conversations.list since deploy.
OTEL fallback found no prod spans matching listSlackChannels / Slack conversations.list since deploy.
Libra has verdicts on 0 of 3 tracked behaviors on prod; 3 are still being checked. Libra checks hourly for 3 days after each deploy.
listSlackChannels (apps/server/src/services/integrations/slack/slack-api.ts) fired a single Superglue slack-list-channels call and returned only the first page. Slack's conversations.list is cursor-paginated (~200 channels/page), so any channel that sorts onto a later page was invisible to the agent.
Impact: an org report whose target Slack channel sorts late (recently created) fails to find it. Concretely , Pirros' weekly "barriers to buy" report posts to #barriers-to-buy, which is public and the cedar_mail bot is a member, but it sits at position ~140 of 166 channels (page 9 of 9). The report agent's list-slack-channels never saw it, marked itself "channel not found in workspace", and skipped both the Slack post and its KB-doc write.
conversations.list (bot cedar_mail / U0BL034EYTS): #barriers-to-buy (C0BNWFQNRJ5) , public, is_member=true, found only after following next_cursor through 9 pages.98426a2a, 21cd2c61 failed with "Slack channel #barriers-to-buy not found in workspace" while the underlying data query succeeded (42 rows).listSlackChannels now calls Slack conversations.list directly (same pattern as the file's other helpers) and follows next_cursor to the end, aggregating every page. Bounded by a 50-page safety cap (logs a warning if a cursor is still pending at the cap). Requests public_channel,private_channel with exclude_archived=false to preserve the previous return shape.
pnpm --filter @zero/server exec vitest run src/services/integrations/slack/__tests__/list-slack-channels-pagination.test.ts , 3 cases: follows the cursor and returns a channel found only on page 2; single page when no cursor; throws on ok:false.
After deploy: the barriers-to-buy report (and any channel-posting automation targeting a late-sorting channel) resolves the channel and posts.
Paired with #2516 (org-cron representative connection health) , both were root causes of Pirros' weekly report not delivering. This one is why it failed even when re-run under a healthy rep.
🤖 Generated with Claude Code
This PR replaces the single-page Superglue channel-listing call with direct cursor-based Slack pagination, preserving channel normalization and adding focused pagination/error tests.
The PR appears safe to merge, with only a non-blocking import-convention issue in the new test.
The pagination implementation follows Slack cursors, aggregates each successful page, and preserves the fields consumed by current callers; the only accepted concern is the test's use of relative imports.
Files Needing Attention: apps/server/src/services/integrations/slack/tests/list-slack-channels-pagination.test.ts
| Filename | Overview |
|---|---|
| apps/server/src/services/integrations/slack/slack-api.ts | Replaces one-page workflow execution with bounded direct Slack cursor pagination while retaining the existing normalized return shape. |
| apps/server/src/services/integrations/slack/tests/list-slack-channels-pagination.test.ts | Adds focused pagination and error tests, but its new relative imports violate the repository's absolute-import convention. |
Libra has not measured any production surfaces for this change yet.