• Adds supervisor/deploy_monitor.py: run_monitor_cycle() is one sampling
    pass, called repeatedly by Deploy Supervisor's own poll loop (03-C's own
    text: not a one-shot call). process_alive/http_health/canary_task/
    validator_approval_rate sampled in order, stopping at the first anomaly.
    
    validator_approval_rate's "approve rate" has no literal definition anywhere
    in 01-M/03-C/04-P (no such execution_event type exists) -- derived instead
    from a verified structural fact in scheduler.finish_task_lifecycle: PASS
    closes straight to done with no bug_record ever created, FAIL/INCONCLUSIVE
    always creates one via judge_root_cause. A task counts as approved iff no
    bug_record(source='validator') exists for it. Baseline is computed by the
    same function looking back MONITORING_WINDOW_HOURS from cutover_at rather
    than persisted as a new column; baseline=None (cold start) never flags an
    anomaly rather than defaulting to 0.
    
    Crash-count/consecutive-http-fail windows are approximated by sample count
    (N = CRASH_WINDOW / MONITOR_SAMPLE_INTERVAL) rather than a true rolling
    time window -- documented simplification, correct as long as sampling stays
    roughly interval-paced.
    
    Caught my own design misreading via the tests: process_alive's monitoring-
    phase anomaly condition is MAX_CRASH_COUNT crashes within CRASH_WINDOW (a
    crash-loop detector), not "currently not alive" -- unlike U-038's health
    check where any single failure fails closed. A single dead reading during
    monitoring is recorded but must not trigger an immediate rollback by itself.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »