Slice 6: notifications per §15

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-05-24 23:09:04 -07:00
parent 1b0968a9a2
commit f67d0aa0db
21 changed files with 3588 additions and 168 deletions
+35 -9
View File
@@ -93,9 +93,20 @@ Required values:
| `OWNER_GITEA_LOGIN` | Your owner-zero Gitea login — gets the owner role on first sign-in. |
| `GITEA_WEBHOOK_SECRET` | A shared secret for the §4.1 webhook signature. |
The LLM-provider settings (`ENABLED_MODELS`, `ANTHROPIC_API_KEY`,
etc.) are not exercised by Slice 1 but are wired through `config.py`
so the next slice can pick them up.
Optional values, picked up at process start:
| Variable | What it is |
| -------------------------- | --------------------------------------------------------- |
| `ENABLED_MODELS` | Comma-separated provider keys for §18 chat (e.g. `claude,gemini`). |
| `ANTHROPIC_API_KEY` etc. | Per-provider keys; missing keys disable that provider. |
| `SMTP_HOST` / `SMTP_PORT` | §15.4 transactional-email adapter target. Empty falls back to logging the envelope to stdout — sufficient for dev and integration tests. |
| `SMTP_USER` / `SMTP_PASSWORD` | SMTP auth credentials. Optional alongside `SMTP_HOST`. |
| `SMTP_STARTTLS` | `1` (default) to negotiate STARTTLS; `0` for plaintext. |
| `EMAIL_FROM` | Envelope From address for §15.4 mail. Defaults to a non-routable placeholder. |
| `EMAIL_FROM_NAME` | Display name on the From header (default `Wiggleverse`). |
| `EMAIL_ENABLED` | `1` (default) to dispatch email; `0` to suppress all sends without disabling the inbox. |
| `EMAIL_BUNDLE_THRESHOLD` | Held-during-quiet-hours threshold for the "Activity while you were away" bundle (default 5, §15.4). |
| `DIGEST_TICK_SECONDS` | Cadence of the §15.5 digest scheduler's loop (default 3600). Tests drive ticks synchronously via `digest.run_tick`. |
### 6. Install dependencies
@@ -150,7 +161,7 @@ button at the bottom opens the propose modal.
## What the build lets you do so far
Slices 15 are shipped. End-to-end paths the app supports today:
Slices 16 are shipped. End-to-end paths the app supports today:
- **Propose → idea PR → merge → super-draft** (Slice 1, §9.1–§9.3).
- **Super-draft body editing** via meta-repo edit branches, with AI
@@ -172,6 +183,21 @@ Slices 15 are shipped. End-to-end paths the app supports today:
§13 in full).
- **§13.1 ownership claim** as a meta-repo PR adding the claimant
to the entry's `owners:` field; admin/owner merges the PR (Slice 5).
- **§15 notifications** end-to-end: a producer-side chokepoint in
`notify.py` fans out from `actions` (and from chat-message
inserts that don't go through the bot) into `notifications`
rows under §15.1's routing rules; §15.6 watches auto-set on the
first substantive gesture and decay after 90 days; the header
badge and the `/inbox` overlay back the live counter via an SSE
stream per §15.3; toasts fire for personal-direct events and for
events landing on the view the user is currently watching;
§15.4 email opts in per category with one-click unsubscribe and
a global opt-out wired to the bounce webhook; §15.5 weekly /
daily digest assembles eligible churn into a single mail; §15.7
reconciles unread state when a scope cursor advances; §15.8
quiet hours hold email and digest while letting the inbox row
still land, and the per-user mute suppresses inbox rows
produced by a specific actor (Slice 6).
This exercises the §4 cache (webhook + reconciler), the §6
permission model in full, the §1 bot wrapper (every Git write goes
@@ -179,11 +205,11 @@ through it, every commit and PR carries the `On-behalf-of:`
trailer), and the §17 routing-collapse rule that lets active and
super-draft surfaces share their endpoints.
Out of scope for the slices shipped so far: notifications (Slice 6,
§15), landing-page and `/philosophy` chrome polish (Slice 7, §14),
the §12 30/90 branch-hygiene timers (Slice 8). The full slicing
plan and the next slice's brief live in
[`docs/DEV.md`](./docs/DEV.md).
Out of scope for the slices shipped so far: landing-page and
`/philosophy` chrome polish, the notification-settings UI surface,
and the admin neighbourhood (Slice 7, §14 + §19.2 candidates); the
§12 30/90 branch-hygiene timers (Slice 8). The full slicing plan
and the next slice's brief live in [`docs/DEV.md`](./docs/DEV.md).
## Verifying it worked