# Weekly digest

> One message a week for whoever runs the team. Conflicts caught, estimated time saved, the most contended code and one next step, posted to Slack and emailed to the owners and admins who opt in.

The weekly digest is a summary of last week for the person who runs the team. It is built from the same numbers as the dashboard's Overview tab. Owners and admins set it up under **Integrations → Weekly digest**. It is off until someone turns it on.

## What's in it

Each digest covers the **7 complete UTC days** before it is sent. A digest sent on Monday covers Monday through Sunday of the previous week.

- **Conflicts caught**, by kind (same files, same code, contract break, merge conflict, duplicate work, dependency order, protected path), next to the number detected.
- **Estimated time saved**, using the same model as the dashboard: each conflict caught while the work was still in progress counts the rework it usually avoids at merge time. Overridden conflicts, false positives, conflicts caught too late and conflicts between two agents of the same developer count zero. The digest includes this explanation.
- **Developers and agents active**: distinct developers, agent installs and sessions.
- **Most contended**: the five files, symbols (`path#name`), contracts (`POST /v1/invoices`) and protected globs that had the most conflicts, with their repositories.
- **Overrides**: how many conflicts a person overrode, with up to three of them and who overrode each one.
- **Open questions**: questions to teammates or agents from the last 30 days that nobody has answered yet, oldest first, with an excerpt of each.
- **Next step**: one action picked from the data. The first rule that matches wins:
  1. A directory contended 3 or more times that no protected path with an owner covers: "Add an owner for `apps/billing/` in `acme/api`: contended 6 times in the last 7 days." This links to **Settings → Coordination policy**, where you add a [protected path](/docs/admin/policies#protected_paths) with an owner.
  2. Questions that have been open for more than a day: answer them.
  3. Three or more overrides: review them, and relax the rule that keeps being overridden.
  4. Conflicts with no Slack connected: connect Slack so blocking conflicts reach the team when they happen.
  5. Only one developer active: invite a teammate. Comity catches conflicts between different developers' agents.
  6. Otherwise: nothing needs your attention.

## Channels

- **Slack** posts a Block Kit message to the channel behind your [Slack integration](/docs/admin/integrations#slack). It has buttons for the dashboard and the next step. If Slack isn't connected, nothing is posted to Slack.
- **Email** goes to every owner and admin who turned on **Email me the digest** in the drawer. Each person opts in for themselves. Members, viewers and billing contacts never get the email, and an admin who is demoted stops getting it. On a self-hosted server, email needs Resend to be configured (`RESEND_API_KEY` and `EMAIL_FROM`).

## Schedule

Pick a UTC day and hour. The default is Monday at 14:00 UTC. The drawer shows the same time in your own time zone.

The worker checks once an hour and sends each org's digest **once per week** (Monday to Sunday, UTC). Changing the schedule never sends a second digest in the same week.

- **Turning the digest on** starts with the next scheduled time. If this week's time has already passed, the first digest goes out next week.
- **Weeks without activity** (no agent sessions and no conflicts) are skipped. The skip is recorded and shows as the last run.
- **Failed sends** (Slack answered with an error, or the email provider failed) are retried on the next hourly checks, up to 3 attempts in total. Retries stop 24 hours after the scheduled time.

## Preview and send now

**Preview** builds the digest from live data and shows the email and the Slack message as they would be sent, without sending anything.

**Send now** delivers it right away to the configured channels, whether or not the schedule is on. It doesn't count as the week's scheduled digest. It can be used once a minute.

## API

All endpoints require an owner or admin with a personal token or a dashboard session.

```sh
# Read the settings, recipients, next send time and last run
curl https://api.comity.so/v1/integrations/digest -H "Authorization: Bearer $COMITY_TOKEN"

# Turn it on for Mondays at 14:00 UTC, Slack and email, and subscribe yourself
curl -X PUT https://api.comity.so/v1/integrations/digest \
  -H "Authorization: Bearer $COMITY_TOKEN" -H "Content-Type: application/json" \
  -d '{"enabled": true, "day": 1, "hour": 14, "channels": ["slack", "email"], "email_me": true}'

# The rendered digest: {digest, slack: {text, blocks}, email: {subject, text, html}}
curl -X POST https://api.comity.so/v1/integrations/digest/preview -H "Authorization: Bearer $COMITY_TOKEN"

# Deliver it now; answers with the run
curl -X POST https://api.comity.so/v1/integrations/digest/send-now -H "Authorization: Bearer $COMITY_TOKEN"
```

`PUT` accepts any subset of `enabled`, `day` (0 = Sunday … 6 = Saturday), `hour` (0–23), `channels` and `email_me`. Turning the digest on with no channels returns 400. `GET` also returns `recipients`, `slack_connected`, `email_available`, `next_send_at` and `last_run`.

A run has a `trigger` (`schedule` or `manual`), a `status`, a `slack` outcome (`sent`, `failed` or `null`), `emails_sent`, `emails_failed` and an `error`. The status is one of:

- `sent`
- `partial`: some channels failed.
- `failed`
- `skipped`: `no_activity`, or `no_channel` when there was nowhere to send it.

`send-now` returns 409 when there is nowhere to send (Slack not connected and nobody opted in to email) and 429 when it was used less than a minute ago.
