Files
Maven/SESSION-05-07-2026.md
T
kami 1eca17f37b reminders: add recurring reminder support
Add cron expression support for recurring reminders using robfig/cron/v3.

Changes:
- Migration #2: ALTER TABLE reminders ADD COLUMN cron TEXT + next_fire_ts INTEGER
- Reminder struct: add Cron and NextFireTs fields
- scanReminder helper extracts full row including nullable cron
- CreateReminder: accept optional cron param, store next_fire_ts = fire_ts
- DueReminders: query on next_fire_ts instead of fire_ts
- RescheduleReminder: new method — parse cron, compute next fire, update
  next_fire_ts or mark fired if no more valid times
- Dispatcher: call RescheduleReminder for cron reminders, MarkReminder for
  one-shots (preserving existing behavior for ID=0 digest skip)
- ReminderCompleter interface: add RescheduleReminder method
- storeAPI adapter: forward RescheduleReminder
- All callers updated: CreateReminder signature includes cron param
- Tests: TestRecurringReminder (store), TestDispatchRecurringReminderReschedules
- Existing tests updated for new signature
2026-07-05 11:46:12 +04:00

131 lines
6.8 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.
# Overnight Session — 2026-07-05
Branch: `overnight-jul5` (from `infra/spine-migrations-encryption-mavweb`)
Architect: `.opencode/agent/architect.md`
---
## Phase 0 — Setup
- [x] Branch `overnight-jul5` created from `infra/spine-migrations-encryption-mavweb`
- [x] `.opencode/agent/architect.md` — orchestrator agent
- [x] `SESSION-05-07-2026.md` — this file
---
## Phase 1 — Housekeeping
| # | Task | Commit | Status |
|---|------|--------|--------|
| 2 | **Makefile hygiene**`-race -coverprofile` in `make test`, add `build-caldav` target | b9248ef | done |
| 3 | **db_key.env hygiene** — remove live key from repo, add to `.gitignore`, keep `.env.example` | already-done | done |
| 4 | **Passkey persistence** — store credentials on disk (JSON file) instead of in-memory map | 44807b6 | done |
Notes:
- Live AES-256 key in `deploy/db_key.env` must be removed from git history. Rotate after.
---
## Phase 2 — Test Coverage Gaps
| # | Task | Commit | Status |
|---|------|--------|--------|
| 5 | **mavcaldav tests**`cmd/mavcaldav/` (314 lines, 0 coverage). CalDAV polling, iCal parsing, value-change filtering | 6daa96b | done |
| 6 | **mavttsd tests**`cmd/mavttsd/` (Piper handler). TTS worker protocol round-trip | a80b919 | done |
| 7 | **voicesink tests**`internal/delivery/voicesink/`. Voice channel dispatch, ErrNoSession mapping | ffef44f | done |
| 8 | **mavweb tests** — extend to cover `main.go` routes (server setup, template parsing, route registration, startup flags) | 185f4f5 | done |
Notes:
- mavweb `handlers_test.go` exists (14 cases). The gap is the non-handler code in `main.go` (549 lines) and `webauthn.go` (213 lines).
- voicesink has 0 tests but is critical — it's the bridge between delivery routing and voice sessions.
---
## Phase 3 — Easy Features (from feature ranking)
| # | Task | Commit | Status |
|---|------|--------|--------|
| 9 | **Command history** — read-only query over existing facts. New endpoint or /dash section | f8ba396 | done |
| 10 | **Revert / undo** — void the latest row for a fact key. Wrapper around existing append-only void mechanism | a02e10f | done |
| 11 | **Stale-reminder burst collapse** — digest overdue reminders on boot instead of firing all at once. Cosmetic: group into a single notification | ca081ce | done |
Notes:
- Command history: the data is already there (`RecentFacts`). This is exposing it better.
- Revert: `internal/store` already supports voiding (`VoidFact`). This is a thin API + confirm gate.
- Burst collapse: the `DueReminders` query in `internal/store/reminders.go` already returns all pending due reminders. The fix is in `internal/loop/gather.go` to collapse them.
---
## Phase 4 — Doable Features
| # | Task | Commit | Status |
|---|------|--------|--------|
| 12 | **Recurring reminders** — cron expression in reminder table. New `cron` column, `next_fire_ts` computed from cron. "trash every tuesday" | — | pending |
| 13 | **Capability model**`scope` column on tools table, migration, UI, tests | 6b80fd0 | done |
| 14 | **Notification batching / digest mode** — morning/evening rollup instead of per-event nudges. Configurable window, accumulated messages in one delivery | — | pending |
| 15 | **Rule trace / explanation engine**`why` query: "why did/didn't you nudge me?" Reads predicate eval log. New `/trace` page or CLI query | — | pending |
| 16 | **Backup/restore automation** — script: `cp` the encrypted DB + re-encrypt-verify + restore flow | — | pending |
Notes:
- Recurring reminders: needs schema migration (#1). Add `cron TEXT` and `next_fire_ts INTEGER` to reminders table.
- Capability model: ranking says "cheap now, expensive to retrofit once tools surface passes ~15 entries."
- Rule trace: the data is ephemeral — can log predicate results per tick to a ring buffer or a `rule_evals` table.
---
## Phase 5 — Web UI Re-imagination
| # | Task | Commit | Status |
|---|------|--------|--------|
| 17 | **In-process auth gate for /tools** — add WeAuthn session check to POST /tools handler. Currently relies solely on wg+nginx | — | pending |
| 18 | **Digest / notification history UI** — section on `/dash` showing batched notifications | — | pending |
| 19 | **Rule trace page** — new `/trace` route showing predicate eval results per rule per tick | — | pending |
| 20 | **Command history page** — new `/history` route showing recent facts/commands | f8ba396 | done |
| 21 | **PWA icons** — add proper icon array to `manifest.json` (generate or inline SVG) | — | pending |
| 22 | **Language unification** — pick Russian or add `lang` URL param toggle | — | pending |
Notes:
- Current `/tools` has no in-process auth — `handlers_test.go` explicitly pins this behavior with `TestEnableTool_NoInProcessAuthGate`.
- PWA manifest currently has `"icons": []` — no icons, mobile add-to-home-screen shows a blank tile.
---
## Phase 6 — Final Pass
| # | Task | Commit | Status |
|---|------|--------|--------|
| 23 | Run `make test` with race detector — fix any races | ccb1d78 | done |
| 24 | `docker compose build` — verify all six daemons compile | ccb1d78 | done |
| 25 | Final review pass — check for debugging artifacts, commented code, TODO stubs | ccb1d78 | done |
---
## Cross-reference: feature ranking → this session
| Ranking item | Session task |
|---|---|
| Infra #2 (mavweb/mavcaldav tests) | #5, #8 |
| Easy: command history | #9 |
| Easy: revert/undo | #10 |
| Easy: capability model | #13 |
| Easy: stale-reminder collapse | #11 |
| Doable: recurring reminders | #12 |
| Doable: passkey persistence | #4 |
| Doable: backup/restore | #16 |
| Doable: testing infra | #2 |
| Doable: rule trace/explanation | #15 |
| Doable: notification batching/digest | #14 |
---
## Caveats & Gotchas
- **Destroy-confirm policy** is listed as "mandatory" in ranking but already shipped in tool executor (PROGRESS.md confirms). No action needed.
- **Quiet-hours definition** is listed as "mandatory" but already shipped (`3623305`). No action needed.
- **At-rest encryption** is listed as infra #1 in ranking but already done (`047a813`). No action needed.
- **Schema migrations** — `migrations.go` exists and is wired. Any new schema change (recurring reminders) uses it.
- **Docker** is already deployed and build-tested (commits `04c8dd1``7683a9b`). The "not build-tested" comment in Dockerfile is stale.
- **Systemd** is explicitly replaced by Docker per commit `04c8dd1`: "Chosen Docker over interim systemd units."
- Race detector may surface pre-existing races in the IPC or worker packages — fix them but don't scope-creep into a full refactor.
- Passkey persistence has a chicken-and-egg problem with cold-start unlock (needs passkey to unlock, passkey needs re-enroll after restart). Fix just the mavweb credential storage; the cold-start unlock flow is a separate feature.