Files
oO/services/recommender/README.md
alvis cba3f1a184 docs(services): update integrations + recommender READMEs for signal abstraction (#78)
integrations/README — replace stale Connector interface and fictional
libsodium vault with the actual SignalSource pattern, SQLite token table,
and real OAuth routes.

recommender/README — document the SignalAggregator pipeline, current
policy registry, and actual /recommend + /feedback contract shapes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 17:17:38 +00:00

2.0 KiB

recommender

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

Contract

POST /api/recommend
  { }  (user inferred from session)
  → { tip: { id, content, source, kind, sourceId?, rationale?, createdAt } }

POST /api/tip/:id/feedback
  { action: "done"|"dismiss"|"snooze"|"helpful"|"not_helpful", dwellMs? }
  → { ok: true }

Pipeline

  1. SignalsSignalAggregator.fetchAll(userId) fans out to all registered SignalSource implementations in parallel. Currently: TodoistSignalSource. Add a source via aggregator.register(new MySource()).
  2. LLM candidatesPOST /generate on ml/serving returns TipCandidate[] from the tip-generator LiteLLM alias.
  3. Scoring — all candidates sent to ml/serving active policy (POST /score/egreedy). Falls back to random if ml/serving is unreachable.
  4. Shadow policies — active policy runs shadow policies in the same request for offline comparison (ADR-0002). Currently: egreedy-v2 shadows egreedy-v1.
  5. PersistencetipViews + tipScores rows written on every serve; tipFeedback row on reaction.
  6. Reward delivery — reaction triggers POST /reward/egreedy on ml/serving with inferred reward value.

Signal normalization

Signals carry features: Record<string, number | boolean> (bandit-ready) and metadata: Record<string, unknown> (source-specific raw fields). The bandit treats features as an opaque dict — sources own their feature names. See ADR-0009.

Policy registry

Policy Status Notes
random Shadow Fallback when ml/serving unreachable
egreedy-v1 Active d=7, ADR-0007
egreedy-v2 Shadow d=12 + profile features, ADR-0012

Shadow → active promotion requires offline sim + online agreement (ADR-0002).

Extraction criteria

Extract to its own process at scaling hotspot: when POST /recommend p99 latency exceeds SLA or when recommendation CPU displaces API serving on shared host.