Commit Graph

7 Commits

Author SHA1 Message Date
kami 03fa52dfd4 Add entity-aware fact resolution against Nexus (Vikunja #279)
facts gain a Subject/EntityID/ResolutionState triple and an async
enrichment worker that resolves free-text subjects to canonical Nexus
entity_ids, mirroring Praxis's enrichment-worker pattern. Ambiguous or
unreachable Nexus never guesses an entity_id — the fact stays pending
or terminal-ambiguous instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ghELqYhZNLub2TXGMazqA
2026-07-20 12:00:37 +04:00
kami 9ff726ee26 Wire durable delivery outbox: migration, store, and dispatcher config
Companion to the dispatcher-side outbox change: adds the
delivery_attempts table migration, Store.BeginDeliveryAttempt/
CompleteDeliveryAttempt/ReconcileStaleDeliveryAttempts, and wires
ReconcileStaleDeliveryAttempts + Config.Outbox into mavend startup
before the tick loop resumes.

Vikunja #270.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ghELqYhZNLub2TXGMazqA
2026-07-20 03:09:33 +04:00
kami 25357bf267 feat: IPC additions for reminders/events/routines, ack tracking, tool management
- Extend IPC wire protocol: add ListReminders, ListEvents, ListProposedRoutines,
  DismissProposedRoutine, AcceptProposedRoutine IPC methods with request/response
  types. Update wire.go with new message kinds.
- Add ack_sends table (migration #5): tracks sev4 telegram repeat-til-ack
  delivery state with rule name + timestamp, indexed for dedup.
- Add Store.DeleteTool: permanently removes a tool row (for dismissing proposed
  tools), idempotent on missing tool.
- Update tick.go: wire new IPC handlers into daemon tick.
2026-07-10 15:49:10 +04:00
kami 59a4e06615 maven: scheduled routines + persistent long-term memory
Two additive proactive/recall features.

Routines (internal/routine): a third proactive class beside reminders
(user-stated) and care rules (world-state) — operator-declared clockwork.
config.routines[] (cron + literal RU body + severity) fire through the
normal dispatcher on schedule. Bodies are literal, not LLM-phrased (can't
hallucinate); rule name routine:<name> keeps them out of the care
autotuner; a cold-start guard seeds on first sight so a restart never
replays a missed schedule. Pure routine.Due + config validation, unit-
tested; the tick driver holds the last-fired map and calls fireRoutines.

Persistent memory (internal/store/memory.go): store.MemoryStore backs the
memory.Store interface with the SAME encrypted sqlite db — survives
restarts and recall text inherits at-rest encryption (no plaintext
sidecar). float32-blob vectors, brute-force cosine (ANN is a later swap
behind the interface), upsert-by-id. The daemon wires st.VectorMemory()
into wireVoice; the in-memory impl stays the test/no-store floor. Closes
the "in-memory only, lost on restart" gap (PROGRESS #8).

Gate green: gofmt/vet clean, -race across routine/config/store/mavend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U2PNdwDj2Gt8YW294J7oSc
2026-07-06 12:37:28 +04:00
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
kami 6b80fd0c0f tools: add scope column for capability model
Add a 'scope' TEXT column (default 'homelab') to the tools table so tools
can be namespaced by scope (e.g. "homelab:restart", "datacenter:reboot").
Backward-compat: bare name defaults to "homelab" scope.

Changes:
- Migration #1: ALTER TABLE tools ADD COLUMN scope
- store.Tool: add Scope field, update all SQL and scanTool()
- ipc.Tool DTO and request types: add Scope field
- CoreAPI interface: pass scope in ProposeTool/EnableTool
- storeAPI adapters: forward scope
- cmd/mavend/voice: pass scope (empty → homelab)
- cmd/mavweb/tools: show scope column in UI tables, hidden fields
- All tests updated for scope field
- Migration test made dynamic (startVer = len(migrations))
2026-07-05 11:40:15 +04:00
kami 047a813278 store: at-rest encryption + schema-migration runner
Two spine infra items (feature-ranking #1, part of the migration prereq):

- migrations.go: PRAGMA user_version runner, empty (no-op) migration slice,
  one tx per step, fail-closed. Mechanism in place before any real schema
  change needs it.
- crypt.go: file-level at-rest encryption. On-disk file is always AES-256-GCM
  ciphertext; decrypted to a tmpfs working copy modernc sqlite operates on;
  re-encrypted atomically on Close, plaintext wiped, key zeroed. Pure stdlib,
  CGO stays off. Fails closed on wrong key/tamper, never falls back to
  plaintext. Key is a 32-byte seam (config db_key_b64/db_key_env today; the
  passkey-derived L3 cold-start key plugs into the same seam later).

Chosen over cgo SQLCipher (would force libsqlcipher + CGO across the project)
and over the ncruces page-level VFS (swaps the driver project-wide); noted as
the upgrade path in a ponytail: comment. Threat model is disk-at-rest only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 21:22:09 +04:00