moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
# 01 β€” Memory Streak Counter
**Author:** CC (Block B design pass)
**Date:** 2026-05-01
**Status:** AWAITING_RATIFICATION
**Estimate:** ~180 LOC + ~3-4h wall-clock
**Touches:** apps/web (3 files), packages/server (1 route), packages/core (1 store)
---
## User story
As a user, when I save a memory or have a meaningful chat session, I want to see a visible streak counter (πŸ”₯ 5 days in a row) somewhere I'll glance at often, so I'm reinforced to come back tomorrow.
## Acceptance criteria
1. Streak chip renders in the desktop StatusBar (bottom-right cluster), wrapped in a HintTooltip explaining the rules.
2. Streak count = consecutive days with at least one memory frame committed (any source: chat, harvest, manual).
3. Streak resets if 24h pass with zero new frames AND zero qualifying activity (configurable). Default: pure 24h gap = reset.
4. Optional "weekend skip" toggle in Settings β†’ Behavior β†’ "Streaks count weekdays only" (default OFF; international users decide).
5. Visible cold-start path: streak=0 day 1 hides chip; streak=1 shows "πŸ”₯ 1 day"; streak=N shows "πŸ”₯ N days" with subtle pulse animation when count increments live.
6. Live increment fires when a new frame lands today and `streak.lastBumpAt` was a previous day β€” no full-day debounce, but client throttles repeat re-renders to once/min.
## UI sketch
```
StatusBar bottom-right (existing cluster):
[memory icon] 12 mem [chat icon] 5 sessions πŸ”₯ 5 days [time]
Hover tooltip:
Memory streak: 5 days
Save at least one memory each day to keep it going.
(Settings β†’ Behavior to skip weekends.)
```
Day-1 user: chip suppressed entirely (no shame for a 0-streak); appears at streak=1 onwards.
Streak break: chip flashes amber for 4 hours after reset, copy reads "Streak broken β€” start fresh today" with action `Got it`.
## Data model
New table `streaks` in personal mind:
```
id INTEGER PRIMARY KEY,
streak_kind TEXT NOT NULL CHECK (streak_kind IN ('memory','chat')),
current_count INTEGER NOT NULL DEFAULT 0,
last_bump_at TEXT NOT NULL, -- ISO date YYYY-MM-DD (no time)
longest_count INTEGER NOT NULL DEFAULT 0,
weekend_skip INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL
```
One row per `streak_kind` per personal mind. v1 ships only `memory` kind; `chat` reserved.
Server route: `GET /api/streaks` β†’ `{ memory: {current, longest, lastBumpAt, weekendSkip} }`. `POST /api/streaks/bump` (called by frame-store on every frame insert) β€” server-side computes current_count by checking lastBumpAt vs today.
## Implementation notes
- Bump trigger: hook into `FrameStore.createIFrame()` callsite OR via a SQLite trigger on `INSERT ON memory_frames`. Trigger is cleaner β€” no orchestrator changes needed.
- Reset detection: pure read-time computation. When client fetches `/api/streaks`, server compares lastBumpAt to today; if gap > 1 day (or > 1 weekday with weekendSkip), reset current to 0 before returning.
- StatusBar wiring: existing `agentStatus`-style hook β†’ new `useStreaks()` hook polling `/api/streaks` every 2 min + on `waggle:frame-saved` event.
## Estimate
- Server route + SQLite migration: ~50 LOC
- `useStreaks()` hook + StatusBar render: ~60 LOC
- Settings toggle: ~30 LOC
- Tests (server bump logic, reset boundary, weekend-skip math): ~40 LOC
- **Total ~180 LOC, ~3-4h with verification.**
## Risks + open questions
1. **Timezone** β€” bump uses server's local TZ (`new Date().toISOString().slice(0,10)`). Travelers crossing dates lose/gain a day. Acceptable v1; document.
2. **What counts as a frame?** β€” currently any frame insert. PM may want to exclude `temporary` importance from bumps. Default: count all non-`deprecated` frames. Open question.
3. **Streak breakage notification** β€” silent reset, or a one-time toast "Streak broken β€” yesterday you missed it"? PM call.
4. **Cosmetic** β€” emoji πŸ”₯ may clash with Hive DS aesthetic. Alternative: `bg-amber-500` flame icon from lucide-react. PM call.
5. **Migration risk** β€” adds new SQLite table. Use migration framework. Idempotent CREATE TABLE IF NOT EXISTS.
## Out of scope (v1)
- Per-workspace streaks (just personal-mind global v1).
- Calendar heatmap (GitHub-style activity grid).
- Streak leaderboards across team. (TEAMS tier only later.)
- Streak freeze / "streak protector" purchases. (Anti-pattern in Waggle DS β€” no buyable shortcuts.)
## PM decisions needed
- [ ] GO / MODIFY / SKIP
- [ ] Frame inclusion rule (all / non-temporary / >threshold importance)
- [ ] Weekend-skip default (OFF / ON / detect locale)
- [ ] Reset notification (silent / toast / amber flash)
- [ ] Emoji vs Lucide icon