release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m33s
release / go (push) Successful in 1m49s
release / integration (push) Successful in 5m42s
release / android (push) Successful in 5m59s
release / Build signed APK (releases and dev) (push) Successful in 6m9s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
Applies rule 32's migration exception: each header still says what the schema was, what changes and what it prevents, but task, milestone, decision and rule ids are replaced by the practice they stood for, the operator quotes by the decision, single-install counts are dropped, and pointers to a deleted package and an external design doc are gone. golang-migrate keeps no checksum, so editing applied migrations' comments is safe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.4 KiB
SQL
57 lines
2.4 KiB
SQL
-- Recommendation tuning lab.
|
|
--
|
|
-- The scoring weights move out of YAML (radio profile) and out of the
|
|
-- systemMixWeights hard-code (daily_mix profile) into DB-backed
|
|
-- settings with live effect — a lab for FINDING good values, which then
|
|
-- get baked into shipped defaults; nobody should need this card to get
|
|
-- good recommendations.
|
|
--
|
|
-- Rows are seeded by the recsettings service's boot reconcile (the
|
|
-- coverart SettingsService pattern), not by this migration, so shipped
|
|
-- defaults live in exactly one place (Go).
|
|
|
|
CREATE TABLE recommendation_weight_profiles (
|
|
profile text PRIMARY KEY
|
|
CONSTRAINT recommendation_weight_profiles_profile_check
|
|
CHECK (profile IN ('radio', 'daily_mix')),
|
|
base_weight double precision NOT NULL,
|
|
like_boost double precision NOT NULL,
|
|
recency_weight double precision NOT NULL,
|
|
skip_penalty double precision NOT NULL,
|
|
jitter_magnitude double precision NOT NULL,
|
|
context_weight double precision NOT NULL,
|
|
similarity_weight double precision NOT NULL,
|
|
taste_weight double precision NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Taste-profile build knobs: engagement half-life + the completion→
|
|
-- engagement curve points (taste.Config's tunable subset).
|
|
CREATE TABLE taste_tuning (
|
|
singleton boolean PRIMARY KEY DEFAULT true
|
|
CONSTRAINT taste_tuning_singleton_check CHECK (singleton),
|
|
half_life_days double precision NOT NULL,
|
|
engagement_hard_skip double precision NOT NULL,
|
|
engagement_neutral double precision NOT NULL,
|
|
engagement_full double precision NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Every knob turn writes one audit row; the metrics trend view
|
|
-- annotates these on its timeline so cause→effect is visible
|
|
-- after a change. changes is a jsonb array of {field, old, new}.
|
|
CREATE TABLE recommendation_tuning_audit (
|
|
id bigserial PRIMARY KEY,
|
|
changed_at timestamptz NOT NULL DEFAULT now(),
|
|
scope text NOT NULL
|
|
CONSTRAINT recommendation_tuning_audit_scope_check
|
|
CHECK (scope IN ('radio', 'daily_mix', 'taste')),
|
|
action text NOT NULL
|
|
CONSTRAINT recommendation_tuning_audit_action_check
|
|
CHECK (action IN ('update', 'reset')),
|
|
changes jsonb NOT NULL
|
|
);
|
|
|
|
CREATE INDEX recommendation_tuning_audit_changed_at_idx
|
|
ON recommendation_tuning_audit (changed_at DESC);
|