profile: unified Profile model (prefs, contexts, consents) #30

Open
opened 2026-04-13 14:23:20 +00:00 by alvis · 0 comments
Owner

Goal

Expand the User schema and ship the unified Profile model from ADR-0014: preferences (quiet hours, tone, allowed tip kinds), contexts (work/home/vacation, manual toggle), consents (per-key, revocable), plus the registry plumbing the orchestrator needs to operate over N agents without hardcoding any of them.

Scope (per ADR-0014)

Schema (migration steps 1, 2, 8)

  • New tables: user_preferences (user_id, scope, key, value_json, source, updated_at), user_consents (user_id, consent_key, granted_at, revoked_at), user_contexts (user_id, name, active, schedule_json, created_at).
  • New columns on users: tone, tip_kinds_json.
  • Backfill users.consent_given rows into user_consents as consent_key=data:core; keep the column for one release, then drop.

Manifest plumbing (migration step 3)

  • Each existing agent (overdue-task, momentum, time-of-day, recent-patterns, focus-area) gets ml/agents/<id>/manifest.py declaring id, version, pref_schema, context_schema, required_consents, output_contract, ttl_sec, and inferred_params (empty list for now; populated by #111-#116).
  • A registry loader in ml/serving exposes the manifest set.

Read-through API (migration step 4)

  • GET /api/profile{ user, prefs (grouped by scope), contexts, consents, agents[] }
  • PATCH /api/profile/prefs/:scope → upsert into user_preferences with source=user
  • PATCH /api/profile/consents → grant/revoke
  • PATCH /api/profile/contexts → activate/deactivate / create
  • GET /api/agents/registry → manifests (TS recommender proxies from ml/serving); admin UI auto-renders forms from each pref_schema

Orchestrator cutover (migration step 5)

  • Replace the hardcoded agent list in the recommender with a registry-driven eligibility filter: required consents granted → not silenced by active context → enabled in prefs.
  • v4-orchestrator prompt template iterates whatever it is handed; no per-agent code paths.

Out of scope

  • The auto-inference logic itself: framework in #111, per-agent fits in #112-#116.
  • Calendar/geo-driven context inference: deliberately deferred (see ADR-0014 §2 note).

Done when

  • All schema migrations land + backfill runs cleanly.
  • All five existing agents ship a manifest; orchestrator consults the registry, not a hardcoded list.
  • GET /api/profile and GET /api/agents/registry return the expected shape.
  • Admin/settings page renders agent prefs from pref_schema (one form per agent, not per-agent code).
  • E2E test: revoking data:todoist consent removes Todoist-derived agents from the next tip.
  • ADR-0014 (this issue is steps 1-5 + 8 of its migration plan)
  • #111 (inference framework — uses the data model this issue defines)
  • #112-#116 (per-agent inference — depend on this + #111)
## Goal Expand the User schema and ship the unified Profile model from ADR-0014: preferences (quiet hours, tone, allowed tip kinds), contexts (work/home/vacation, manual toggle), consents (per-key, revocable), plus the registry plumbing the orchestrator needs to operate over N agents without hardcoding any of them. ## Scope (per ADR-0014) ### Schema (migration steps 1, 2, 8) - New tables: `user_preferences (user_id, scope, key, value_json, source, updated_at)`, `user_consents (user_id, consent_key, granted_at, revoked_at)`, `user_contexts (user_id, name, active, schedule_json, created_at)`. - New columns on `users`: `tone`, `tip_kinds_json`. - Backfill `users.consent_given` rows into `user_consents` as `consent_key=data:core`; keep the column for one release, then drop. ### Manifest plumbing (migration step 3) - Each existing agent (`overdue-task`, `momentum`, `time-of-day`, `recent-patterns`, `focus-area`) gets `ml/agents/<id>/manifest.py` declaring `id`, `version`, `pref_schema`, `context_schema`, `required_consents`, `output_contract`, `ttl_sec`, and `inferred_params` (empty list for now; populated by #111-#116). - A registry loader in `ml/serving` exposes the manifest set. ### Read-through API (migration step 4) - `GET /api/profile` → `{ user, prefs (grouped by scope), contexts, consents, agents[] }` - `PATCH /api/profile/prefs/:scope` → upsert into `user_preferences` with `source=user` - `PATCH /api/profile/consents` → grant/revoke - `PATCH /api/profile/contexts` → activate/deactivate / create - `GET /api/agents/registry` → manifests (TS recommender proxies from `ml/serving`); admin UI auto-renders forms from each `pref_schema` ### Orchestrator cutover (migration step 5) - Replace the hardcoded agent list in the recommender with a registry-driven eligibility filter: required consents granted → not silenced by active context → enabled in prefs. - `v4-orchestrator` prompt template iterates whatever it is handed; no per-agent code paths. ## Out of scope - The auto-inference logic itself: framework in #111, per-agent fits in #112-#116. - Calendar/geo-driven context inference: deliberately deferred (see ADR-0014 §2 note). ## Done when - All schema migrations land + backfill runs cleanly. - All five existing agents ship a manifest; orchestrator consults the registry, not a hardcoded list. - `GET /api/profile` and `GET /api/agents/registry` return the expected shape. - Admin/settings page renders agent prefs from `pref_schema` (one form per agent, not per-agent code). - E2E test: revoking `data:todoist` consent removes Todoist-derived agents from the next tip. ## Related - ADR-0014 (this issue is steps 1-5 + 8 of its migration plan) - #111 (inference framework — uses the data model this issue defines) - #112-#116 (per-agent inference — depend on this + #111)
alvis added this to the M2 — AI tips + multi-source signals milestone 2026-04-13 14:23:20 +00:00
alvis added the backend label 2026-04-13 14:23:20 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alvis/oO#30