Repository navigation
Give the Slack agent a Postgres analytics warehouse and finish its Sentry lab - #11
Conversation
instrument.ts turns gen AI inputs and outputs off for the whole app. agent.ts sets telemetry.recordInputs and recordOutputs per call, and app.ts passes true for a channel mention and false for a DM. The root span carries slack.channel_type so the trace shows why content is missing. In Sentry 11.0.0 a per-call boolean beats the dataCollection default, so the DM path never records the conversation. Co-authored-by: Claude <[email protected]>
…ntry lab The bot now answers metric questions from a seeded Postgres table through one analytics.scan span per warehouse query, tagged with the metric, the range length, and the row count. The eve framework and tsx are gone; the process starts with node --import ./src/instrument.ts. Lab 4, the runsheet, the prompt sheet, and the solution patch follow the new shape. Co-authored-by: Claude <[email protected]>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 5 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.
| // Prompts and replies are off by default for this app; src/agent.ts turns | ||
| // them on per call when the message is in a channel. | ||
| dataCollection: { genAI: { inputs: false, outputs: false } }, | ||
| }); |
There was a problem hiding this comment.
Lab solutions already in starting apps
High Severity
Lab 2 and Lab 4 still ask students to add Sentry to apps that have none, and ./scripts/solution.sh applies a patch on that basis, but this change already lands the full instrumentation in apps/slack-agent and apps/storefront. The instrument-by-prompt step is a no-op, and git apply --check on the solution patches fails.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.
| openrouter: { cacheControl: { type: "ephemeral" } }, | ||
| }; | ||
|
|
||
| const TODAY = new Date().toISOString().slice(0, 10); |
There was a problem hiding this comment.
Prompt date disagrees with validation
Medium Severity
SYSTEM_PROMPT sets today's date from toISOString() (UTC), while validateQuery and db:seed use the host's local calendar day. After UTC midnight, the model treats tomorrow as today and warehouse queries that end on that date are rejected as after today.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.
| throw new AnalyticsQueryError( | ||
| `The range ${from} to ${to} is ${rangeDays} days, outside the 90-day retention window.`, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Old lookback ranges are not rejected
Medium Severity
validateQuery only rejects a span longer than 90 days. A range that starts before the warehouse (for example the previous 90 days when comparing a full window) still succeeds and returns empty rows, so the assistant reports zeros instead of the lookback error the system prompt describes.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.
| const previousPoints = previousDates.map((date, i) => ({ | ||
| date, | ||
| value: output.series.previous[i] ?? 0, | ||
| })); |
There was a problem hiding this comment.
Comparison charts shift values by index
Medium Severity
compare_periods returns only value arrays from dates that have rows, and comparePeriodsBlocks then pairs those values with every calendar day in the range by index. A missing day at the start of the window slides later values onto the wrong dates and pads the end with zeros.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.
| rowCount: rows.length, | ||
| total: total(rows, unit), | ||
| rows: rows.slice(0, 200), | ||
| groupTotals: groupBy ? groupTotalsOf(rows, groupBy, unit) : undefined, |
There was a problem hiding this comment.
Grouped charts use truncated rows
Medium Severity
query_metric keeps full groupTotals but returns only the first 200 rows. Grouped charts in queryMetricBlocks series from that truncated rows list, so a 90-day breakdown by plan, platform, country, or path plots only the earliest days while the card title still names the full range.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3b6dd15. Configure here.


Lab 4 now runs on a plain Node Slack bot with a seeded Postgres analytics warehouse. Each warehouse query is one
analytics.scanspan tagged with the metric, the range length, and the row count. Prompts and replies are recorded in channels only, never in a direct message. The eve framework and tsx are removed. The lab doc, runsheet, prompt sheet, and solution patch match the new code.Checks:
npm run typecheckandnpm test(14 tests) inapps/slack-agentpass.Created with Claude Code