-- +goose Up -- Seed the prior only requirement_time_to_fill model, a discrete time survival forecast of how long a staffing -- requirement stays open before it is filled. It rides the SAME coefficient store as the other MAG models (no -- new tables). Its OutputKind is opportunity_score: the served number is P(filled within a horizon) = 1 minus -- the cumulative survival, an OPPORTUNITY level probability, never a per candidate score, so the frozen v1.4.0 -- engine stays the only per candidate scorer. The per month hazard vector is stored as one coefficient row per -- month (hazard_month_1 .. hazard_month_12); serving reads them, forms the survival curve as the running product -- of one minus the hazard, and reports the fill within horizon probability with the per month hazard list as the -- interpretable evidence. -- -- The prior only v1 hazard is a DEFENSIBLE constant: 0.25 per month, so the median time to fill is about two and -- a half months (survival 0.75^t crosses 0.5 near month 2.4), a reasonable federal staffing baseline. Every -- month carries the same 0.25 the day it ships, and a learned per month hazard lights up automatically as filled -- and still open requirement durations accrue and cmd/train-model fits the empirical hazard. A discrete hazard -- model needs NO calibration bins (the survival is exact from the hazards), so none are seeded. INSERT INTO aedt_learned_models (model_key, version, family, output_kind, feature_spec, champion, notes) VALUES ( 'requirement_time_to_fill', 1, 'discrete_hazard', 'opportunity_score', '{"features": [{"name": "hazard_curve", "source": "requirement_fill_durations", "horizon_months": 12}]}', true, 'Prior only v1. A constant 0.25 per month fill hazard (median time to fill about two and a half months), a defensible federal staffing baseline. Learned per month hazards light up as filled and still open requirement durations accrue. OutputKind opportunity_score expressing P(filled within a horizon), never a per candidate score.' ) ON CONFLICT (model_key, version) DO NOTHING; -- The 12 month baseline hazard curve, each month at the constant 0.25 prior. The intercept row is 0.0 (a -- discrete hazard model has no bias term; it is stored only so the store shape matches the other models). INSERT INTO aedt_model_coefficients (model_key, version, feature_name, coefficient) VALUES ('requirement_time_to_fill', 1, 'intercept', 0.0000000000), ('requirement_time_to_fill', 1, 'hazard_month_1', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_2', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_3', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_4', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_5', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_6', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_7', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_8', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_9', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_10', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_11', 0.2500000000), ('requirement_time_to_fill', 1, 'hazard_month_12', 0.2500000000) ON CONFLICT (model_key, version, feature_name) DO NOTHING; -- +goose Down DELETE FROM aedt_model_coefficients WHERE model_key = 'requirement_time_to_fill'; DELETE FROM aedt_learned_models WHERE model_key = 'requirement_time_to_fill';