PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 11s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 8s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 1s
Folds into the same branch as the Zulip delivery change, as instructed. FINDING 1 - the Firecrawl probe path was wrong; the service is fine. scripts/daily-infra-report.py probed http://192.168.68.7:3002/health, which Firecrawl does not serve - it 404s. The root answers 200 with {"message":"Firecrawl API",...}. Live 2026-09-26: Firecrawl(/) -> 200 Firecrawl(/health) -> 404 <- what the report was showing The probe is now the root, which is its liveness endpoint. FINDING 2 - the Network Endpoints classification was wrong twice over. It read: color = green if code in (200,302,401) else (yellow if code >= 400 else red). Two defects: (a) it ignored the fleet's own probe policy, codified 2026-09-14 in the monitoring contracts: ANY HTTP status proves the service answered, so the service is ALIVE, and only a failed CONNECTION is a failed probe. A 404 from a wrong path is not a service fault. (b) was a STRING comparison. Reproduced: 301 -> red (a live redirect rendered as a failure), 404 -> yellow, 500 -> yellow (a real server error softened to a warning). Replaced with classify_endpoint(), which returns: any 2xx/3xx/4xx -> green 'alive' (code still shown) 5xx -> yellow 'server error' (kept distinct from 4xx, as asked) 000/no answer -> red 'no connection' Verified against the live endpoints after the change: Gitea 200, Authentik 302, Zulip 302, Pulse 200, Proxmox 200, SearXNG 200, Firecrawl 200 - all green/alive; the only red state is a genuine no-connection. ALSO CHECKED, as asked: scripts/search-stack-check.py does NOT depend on the wrong route. It POSTs to {FIRECRAWL_URL}/v1/scrape with formats=[markdown], and that path really works - live POST returned HTTP 200 and 180 chars of markdown for https://example.com. It was never using /health. prose-lint: PASSED.