# Plan: Behavioral Memory — How I Do Stuff

**Goal:** Maven builds a rich behavioral model of the user over time: habits, routines, preferences, recurring tasks, deadlines, and commitments. She uses this model to proactively propose plans, surface reminders, and adjust her behavior — all grounded in the existing fact/event/note stores.

**Done when:**
- `internal/memory/behavior.go` — behavioral model builder reads facts, events, notes, nudges, reminders, tools, calendar events
- Model is exposed as a structured profile: `{"routines": [...], "preferences": {...}, "recurring_tasks": [...], "typical_schedule": {...}}`
- LLM generates this profile periodically (daily) and stores it as a note/fact
- Proactive loop uses the profile to propose daily plans: "сегодня ты обычно делаешь X, Y, Z. напомнить?"
- Profile is queryable via voice: "что я обычно делаю по вторникам?"
- Profile updates on fact write — not just periodic — so a new "walk" fact immediately adjusts the walking schedule

**Scope:**
- `internal/memory/behavior.go` — behavior builder
- `internal/memory/profile.go` — profile data structures (routines, preferences, schedule, commitments)
- Reuses `internal/llm.Client` for profile generation
- Reuses `internal/pattern/detector.go` for interval detection on behavioral data
- Extends `internal/router/intent.go` — `IntentQuery` extended with behavioral sub-queries
- Reuses `internal/delivery.Dispatcher` for surfacing proposals as nudges

**Steps:**
1. Design profile schema: `BehaviorProfile` struct with `Routines []Routine`, `Preferences map[string]string`, `RecurringTasks []Task`, `WeeklySchedule map[string][]Activity`
2. Create `internal/memory/behavior.go` — `Builder` that reads `store.RecentFacts(1000)`, `store.EventsFor` (all action+object combos), `store.RecentNotes(500)`, `store.ListReminders`
3. Implement profile generation — prompt for `llm.Client` that takes raw facts and outputs a structured JSON profile; stores result as a fact (`kind=config, key=behavior_profile`)
4. Create `internal/memory/planner.go` — reads the profile each morning (via routine cron `"0 8 * * *"`) and proposes a daily plan through `dispatcher.DispatchNudge`
5. Add real-time updates — when a fact is written via `WriteFact`, the behavior builder incrementally updates the relevant profile section (append-only, no full rebuild)
6. Wire voice query — `"что я обычно делаю?"` routes to `IntentQuery` → behavior profile lookup → LLM-phrased answer
7. Add IPC read method `MethodGetBehaviorProfile` so mavweb can display it on `/dash`
8. Test with synthetic fact history — verify weekly schedule is correctly inferred

---

## Status (2026-08-01) — partially shipped, deliberately narrowed

Shipped on `overnight/behavior-profile`:

- `internal/memory/behavior.go` — `BuildProfile` counts habits per weekday out of
  self-facts: distinct-day counts (`MinHabitDays = 2`), a median time-of-day, and
  `FormatWeekdayRU` / `FormatOverallRU` for the spoken answer.
- `internal/router/habit.go` — `ParseHabitQuery`, which requires a habit marker
  ("обычно", "каждую", "привычки", …) and parses the weekday deterministically.
- `cmd/mavend/actions_query.go` — a `habits` query source, so "что я обычно делаю
  по вторникам?" is answered.

**Not shipped, and not to be shipped as written:**

- *Step 3, LLM-generated profile stored as a fact.* The profile is COUNTED, not
  generated. A 1.7B asked to summarise a year of habits produces fluent claims
  about the owner's life that no row supports, and a wrong claim about him is the
  most expensive kind of wrong maven can be. Counting is verifiable and cheap.
- *Step 5, incremental updates on fact write.* There is no cache to keep fresh —
  the profile is recomputed on the question, so a new fact is already in the next
  answer. A cached profile that can disagree with its own rows is two truths.
- *Step 4, proactive daily plan proposals via the dispatcher.* Maven is not a nag,
  and a nudge at 08:00 every day proposing the day is the definition of one. The
  sanctioned path from "she noticed a pattern" to "she acts on it" already exists:
  `internal/pattern/detector.go` proposes a routine, and the owner accepts it on
  `/routines`. It goes through him.

Still open, if wanted later: `MethodGetBehaviorProfile` + a `/dash` panel (step 7).
The counted profile needs no new IPC method to be *asked* about — the query source
reads `RecentFacts` over the existing surface — so this is a display concern only.
