Lint / Python (flake8) (push) Successful in 1m8s
Security / Python Security (bandit) (push) Successful in 56s
Test / Python Tests (pytest) (push) Successful in 43s
Lint / Python (flake8) (pull_request) Successful in 50s
Lint / JS (eslint) (pull_request) Successful in 30s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 55s
Test / Python Tests (pytest) (pull_request) Successful in 50s
Lint / JS (eslint) (push) Successful in 16m17s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Trace a cord: pick a panel port, press Start, and unplug the cord at the panel. The page polls a new admin-only endpoint that reads every switch port's state from UniFi (cached 2 s), shows the one port that dropped with a button to record the cable, and confirms when it's plugged back in. Several ports dropping at once, or none within 3 minutes, is explained rather than guessed at. Mismatch alerts: the monitor runs the cutsheet check every poll. Each mismatched installed run (wrong neighbor, no link, missing port, port conflict) keeps one cable_mismatch event on its switch, resolved when fixed, and opens a P4 ticket after cutsheet.mismatch_ticket_hours (default 24, 0 never). Suppressing the switch or port stops the ticket. Also fixes buttons with the hidden attribute still showing, which left a Delete button on the new-cable form. Closes #12 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>