Skip to content
Merged
20 changes: 20 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ Registry:
| `suggest_feeds` | no (validates only) | — |
| `add_feed` | yes | no |
| `remove_feed` | yes | no |
| `list_personal_feeds` | no | — |
| `suggest_personal_feeds` | no (validates only) | — |
| `add_personal_feed` | yes | no |
| `remove_personal_feed` | yes | no |
| `set_presence` | self only (own status/activity, persisted) | no |
| `set_nickname` | self only (own guild nickname) | no |
| `server_stats` | no | — |
Expand Down Expand Up @@ -257,6 +261,21 @@ triggerable via the `run_digest` tool. There is **no user input anywhere in this
are truncated to 500 chars before the model sees them.
- **Exactly-once posting.** Items are marked **seen** (`seen` table) only *after* a successful post,
so a failed post retries the same items next time rather than dropping them.
- **A personal, DM'd sibling.** `run_personal_digest_job` is the same mechanism — fetch, dedupe,
summarize — pointed at a second, separately-curated `personal_feeds` list, delivered to
`PERSONAL_DIGEST_CHANNEL_ID` if set, else DMed directly to the owner — same fallback shape and
the same "deploy owner's choice of destination and privacy, not Roger's" reasoning as Giga
Brain's periodic check-in (§12). It shares the `digest` brain's model and daily budget; it's a
second job, not a second brain. Curated the same way — `suggest_personal_feeds` /
`add_personal_feed` / `remove_personal_feed` / `list_personal_feeds` mirror the public digest's
four curation tools exactly. Scheduled unconditionally, same as Giga Brain's interval check —
the job itself decides "not configured" (no feeds) rather than the caller gating on whether a
seed env var happens to still be set, so feeds curated live via chat are actually delivered.
- **One caveat: `seen` is shared.** Dedup is keyed on `(feed_url, entry_id)` globally, not per
list — a URL curated into *both* `feeds` and `personal_feeds` is only ever delivered by
whichever job runs first that day (personal digest defaults to `PERSONAL_DIGEST_HOUR=7`, before
the public digest's `DIGEST_HOUR=8`). Don't add the same feed to both lists if you want it in
both digests.

## §10 Persistence

Expand All @@ -272,6 +291,7 @@ behaviour adds rows, not migrations.
| `admin_log` | Owner admin conversation memory, per channel (§6) |
| `gigabrain_log` | Owner gigabrain conversation memory, per channel (§12) |
| `feeds` | The curated digest feed list (§9) |
| `personal_feeds` | The owner's personal digest feed list, curated separately from `feeds` (§9) |
| `meta` | Small key/value bot state (persisted presence outfit, gigabrain's last-run date) — never pruned |

## §11 LLM layer & budgets
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ Feature-complete across the planned phases:
- **Digest** — a scheduled daily RSS/Atom summary (also triggerable via `/roger run the digest
now`), deduped so nothing posts twice. Roger curates its own feed list: `DIGEST_FEEDS` seeds it
once, then Roger validates candidates against the live web and adds or drops them on request.
A second, privately-curated feed list can also be DM'd to the owner only
(`PERSONAL_DIGEST_FEEDS`), on its own schedule.

Runs as a non-root, read-only-rootfs container. ~110 tests cover the guard rules, the tool loop
Runs as a non-root, read-only-rootfs container. ~275 tests cover the guard rules, the tool loop
(including channel creation with access presets and the confirm-gated edit, post, and reorder
tools), the rate limiter, and the digest and feed-curation paths.

Expand Down
63 changes: 63 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Roadmap

[`BACKLOG.md`](BACKLOG.md) is explicit that it's *"not a feature wishlist — it's the
production-hardening layer."* This file is the other half: new capability, not hardening — ideas
for Roger doing more without the owner personally driving every step, and for growing a small,
personal-interest Discord server that doesn't have a lot going on day to day.

Community/culture planning (what to post about, tone, events — not code) lives separately in
[`community-discord`](https://github.com/R055LE/community-discord), since Roger and the server it
runs in are different things. This file is the "how Roger could help" side.

Same effort key as BACKLOG: **S** ≈ an afternoon, **M** ≈ a day or two, **L** ≈ multi-day.

---

## 1. Personal digest — **S/M** — *shipped*

A feed roundup DM'd to the owner only, separate list and schedule from the public digest. Directly
answers "I'm out of the loop" — reuses Digest's existing RSS/feeds/curation plumbing rather than
building anything new, per [ADR-style discussion in the
spec](docs/superpowers/specs/2026-08-18-personal-digest-design.md).

*Why it's first:* smallest of the four, reuses infrastructure that already exists and is already
tested, and is the most direct fix for the stated pain.

## 2. Proactive public content ("Spark") — **L** — *idea only*

The flagship. A new scheduled capability that posts unprompted to a public channel to spark
discussion — reacting to real fetched items (AI/tech headlines, story recs, art highlights, open
questions), not free-generated commentary that could confidently state something wrong. Same risk
shape as Digest (§9 of `ARCHITECTURE.md`): scheduled, no user in the path, posts a message, nothing
destructive.

Needs its own design pass — content grounding, cadence, tone, and probably its own ADR given it's a
new class of unprompted public output. Not spec'd yet.

*Why it's not first:* biggest unknown, and the personal digest's grounding-vs-hallucination question
(item 1) is a smaller version of the same problem worth solving first.

## 3. Model allocation pass — **S** — *idea only*

Give content-generation brains (Spark once it exists, Giga Brain now) their own tuned/creative model
chain distinct from admin's tool-calling chain. There's real headroom to do this — Giga Brain's spend
has been low. Mostly config + evaluation, not new code.

*Why it's not standalone:* rides along with items 1 and 2 rather than being picked up on its own —
worth doing once there's actual creative-generation output to tune against.

## 4. Parked — self-serve commands for other members

Not a stated pain point today (the server's small, and the ask was about the owner's own bottleneck,
not delegating to others). Noted so it doesn't get lost if the server grows enough that it becomes
one.

---

## Deliberately not doing (for now)

- **Scraping non-RSS sources** for items 1/2. Feedparser-only, matching Digest's existing
constraint. A site with no feed is a future idea, not a blocker.
- **A distinct model/budget for the personal digest.** It shares Digest's `MODEL_DIGEST` chain and
`DAILY_TOKENS_DIGEST`/`DAILY_USD_DIGEST` cap — a second job, not a second brain. Revisit if the
editorial angle (item 2 territory) ever gets folded into it.
3 changes: 3 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ services:
DIGEST_FEEDS: ${DIGEST_FEEDS:-}
DIGEST_CHANNEL_ID: ${DIGEST_CHANNEL_ID:-}
DIGEST_HOUR: ${DIGEST_HOUR:-8}
PERSONAL_DIGEST_FEEDS: ${PERSONAL_DIGEST_FEEDS:-}
PERSONAL_DIGEST_CHANNEL_ID: ${PERSONAL_DIGEST_CHANNEL_ID:-}
PERSONAL_DIGEST_HOUR: ${PERSONAL_DIGEST_HOUR:-7}
OPS_CHANNEL_ID: ${OPS_CHANNEL_ID:-}
METRICS_PORT: ${METRICS_PORT:-9108}
TZ: ${TZ:-America/Detroit}
Expand Down
Loading