Files
waggle-os/docs/addiction-features/04-weekly-wins-digest.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

127 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 04 — Memory Wins Digest (Weekly)
**Author:** CC (Block B design pass)
**Date:** 2026-05-01
**Status:** AWAITING_RATIFICATION
**Estimate:** ~250 LOC + ~4-5h wall-clock
**Touches:** apps/web (1 component + 1 tab in Memory app), packages/server (1 cron job + 1 route), packages/core (1 generator)
---
## User story
Once a week (Monday morning by default), I want a summary card showing how Waggle's memory paid off the prior week — N facts saved, N agent recalls that used them, estimated minutes saved on context-explaining — so I can quantify the value and feel the compounding effect.
## Acceptance criteria
1. Weekly digest fires once per week (configurable day/hour, default Monday 09:00 local).
2. Delivered as a Memory app tab card + an in-app banner on first desktop mount of the week.
3. Card content (3 metrics + 1 narrative line):
- Frames saved this week: N
- Recalls that hit a saved frame: M
- Estimated time saved (M × 9min context-restore baseline): ~T minutes
- Narrative: "Your top theme this week: <theme>. Top decision: <decision>"
4. Card persists in Memory app's "Wins" tab indefinitely — historical record of weekly progress, not just one-time.
5. First-week edge case: if user has < 7 days of history, banner suppressed but Wins tab shows "Come back next week for your first digest" placeholder.
## UI sketch
```
Memory App > Wins tab:
┌─ Week of April 24-30 ──────────────────────────────────────┐
│ ▲ 12 frames saved ▲ 5 agent recalls ⏱ ~45 min saved │
│ │
│ Top theme: API rate limiting + auth-rewrite │
│ Top decision: Ship migrations Wednesday │
│ │
│ [Open Memory] [Open Last Decision Source] │
└────────────────────────────────────────────────────────────┘
┌─ Week of April 17-23 ──────────────────────────────────────┐
│ ▲ 8 frames · ▲ 3 recalls · ⏱ ~27 min saved │
│ Top theme: Onboarding wizard polish │
└────────────────────────────────────────────────────────────┘
(older weeks collapsed by default, click to expand)
Banner on Monday morning:
[Trophy icon] This week saved you ~45 min — see the breakdown
[Open Wins] [✕]
```
## Data model
New table `weekly_wins`:
```
id INTEGER PRIMARY KEY,
week_start TEXT NOT NULL UNIQUE, -- 'YYYY-MM-DD' (Monday)
frame_count INTEGER NOT NULL,
recall_count INTEGER NOT NULL,
estimated_minutes_saved INTEGER NOT NULL,
top_theme TEXT,
top_decision TEXT,
top_decision_source_session_id TEXT,
generated_at TEXT NOT NULL,
delivered_at TEXT -- nullable until banner shown
```
For `recall_count`, need to instrument frame retrieval:
- Existing `HybridSearch.search()` already returns frame IDs
- Add `RecallEvent` log: every search/retrieval that hits a frame logs `{ frame_id, ts, source: 'agent' | 'manual' }` to a `recall_events` table
- Aggregate weekly count per (week, agent-source-only)
## Server-side generator
Cron runs Monday 00:30 local (off-peak):
1. Query frames where `created_at >= weekStart AND created_at < weekStart+7d`
2. Query recall_events where `source='agent' AND ts in [weekStart, weekStart+7d]`
3. Compute estimated_minutes_saved = recall_count × 9 (calibrated baseline; configurable)
4. Theme extraction: LLM call ("From these N frames, what's the dominant theme in 5-10 words?")
5. Top decision: highest-importance critical/important frame matching decision pattern from the week
6. Insert row, set delivered_at=null, await client poll
Estimated minutes baseline (the "9 min context-restore"): documented derivation needed; placeholder until UX research lands.
## Implementation notes
- Recall instrumentation is the hardest part — needs hook in `HybridSearch.search()` callsite to log frame IDs returned and identifier of the consumer (agent loop vs manual UI search).
- Weekly cron: trivial extension of cron infrastructure; runs `generateWeeklyWins(weekStart)` on schedule.
- Wins tab in Memory app: paginate if N > 12 weeks.
- Edge: time zones again — week boundary is server-local Monday 00:00. Document.
## Estimate
- Recall events table + instrumentation: ~70 LOC (touches HybridSearch + agent-loop)
- Generator + cron: ~80 LOC
- Server route `/api/weekly-wins`: ~30 LOC
- WinsCard + WinsTab components: ~80 LOC
- Banner + ack route: ~30 LOC
- Tests: ~50 LOC
- **Total ~340 LOC, ~4-5h with verification.**
## Risks + open questions
1. **Recall instrumentation** is the cost driver — need to wire `HybridSearch` to log every retrieval. Hot path; throttle/buffer logs to avoid SQLite write storms.
2. **Estimated-minutes-saved calibration** — 9 min baseline is a guess. Run a small UX study or pilot a percentile estimate. v1: hardcode + flag for revision.
3. **First week** — user installs Monday afternoon, what do they see Tuesday? Nothing — wait for next Monday. Banner suppressed for ~7 days.
4. **Theme/decision LLM cost** — 1 call/week × ~700 tokens ≈ $0.01/user/week. Negligible.
5. **Privacy** — frames may contain sensitive content; theme summary on personal mind only, not Team/shared workspaces. Hard rule: no cross-workspace digests.
6. **What counts as a "recall"** — open question. Agent retrieval via `recall_memory` MCP tool? Hybrid search hits during chat? UI-driven Memory app search? Default: instrument all three; aggregate by source.
## Out of scope (v1)
- Comparison to prior week ("up 30% from last week") — wait until 4+ weeks of data.
- Per-workspace digests — global personal-mind digest only v1.
- Email digest delivery — in-app only.
- "Share to team" affordance.
- Streak integration ("you've maintained a 4-week digest streak"). (Streak feature is separate; wait until both exist.)
## PM decisions needed
- [ ] GO / MODIFY / SKIP
- [ ] Default delivery day/hour (Monday 09:00 reasonable? Friday end-of-week instead?)
- [ ] Recall sources to count (agent only / agent+UI / all)
- [ ] Estimated-minutes baseline (9 min default, or skip the metric until calibrated?)
- [ ] Banner vs. tab-only delivery (can banner be opt-out?)
- [ ] Theme extraction model (Sonnet / Haiku)