Files
oO/services/recommender/README.md
alvis 7f173f88d3 refactor: architecture revision — modular monolith, auth-commit, event protobuf, privacy-from-day-0
- ADR-0003: modular monolith for Phase 0 with documented extraction triggers
- ADR-0004: Auth.js + OIDC-shaped boundary; dedicated provider when mobile ships
- ADR-0005: protobuf for events, OpenAPI for HTTP, schema-registry CI gate
- New architecture docs: data-model, metrics (magic proxies), privacy (Phase-0 feature)
- Prime directives updated: privacy-as-feature, modular-by-package-deployable-by-stage
- Roadmap revised: Apple OAuth deferred to M1; web push in M1; k3s intermediate; tip-kind-aware UI
- PLAN updated: Phase-0 deletion endpoint, metrics baseline, compose profiles, import-boundary lint
- License decision in README (ARR with OSS plan in Phase 5)
2026-04-13 14:36:11 +00:00

1.4 KiB

recommender

The core of oO. Takes a user + a context, returns one tip.

Contract

POST /recommend
  { user_id, context?: { time, timezone, client, ... } }
  → { tip: { id, kind: "todo"|"advice", title, body, source, deep_link, meta } }

POST /feedback
  { user_id, tip_id, reaction: "done"|"snooze"|"dismiss", at }

Internals (stable seams)

  • Candidate sources — pluggable async generators. v0: Todoist tasks via integrations. Later: advice library, calendar nudges, health prompts.
  • Feature assembler — fills the context blob (inline in Phase 0; calls feature store from M1). Never inlined into policy code.
  • Policy registryPolicy.pick(candidates, context) → tip. Named entries:
    • random — v0 (Phase 0).
    • bandit.linucb.pooled — v1 (Phase 1). Global-then-personalize: pooled features shared across users; per-user residual once data allows.
    • remote — delegates to ml/serving FastAPI scorer (Phase 1+).
  • Shadow hook — every request optionally runs N shadow policies in parallel and logs their picks + estimated rewards. Promotion from shadow → A/B → launch is a separate, deliberate step (ADR-0002).
  • TipInstance persistence — every decision writes context_snapshot (features seen at decision time). This is what makes offline replay honest.

Phase 0 goal

RandomPolicy only. The service, contract, registry, shadow hook, and tip-instance persistence all exist; no ML yet.