Finish #25's deferred PHP-fatals signal, sourced from the WP_DEBUG log
(/tmp/wp-debug.log) that #30's Security toggle writes — not the access log
(which can't carry it):
- get_php_errors: one bounded docker exec (marker-guarded tail -c, 15s single-
worker timeout) distinguishes logging-off / no-log from on-but-clean, then
parses [time] PHP <Level>: <msg> into severity counts (fatal/warning/notice/
deprecated; Parse + Recoverable-fatal fold into fatal) + the 25 most-recent
entries (messages capped, stack-trace lines skipped).
- Merged into GET /sites/<id>/analytics as php_errors; a PHP errors panel added
to the Analytics tab with an 'enable WP_DEBUG on the Security tab' empty state.
- Supplies the per-site error signal #27's error-spike rule wanted.
7 new tests (classification, parse/skip-traces, off/empty/unavailable, capping);
full backend suite 218 passed / 12 skipped; frontend lint-clean + production build.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>