Skip to content

wake-briefing: the debug.log fatal signal is a network-shared file but is emitted once per site, so one fatal reads as N #3516

Description

@chubes4

What happened

Today's composed WAKE.md (2026-09-18 18:01 GMT) on the Extra Chill network listed eleven separate lines:

- extrachill.com — ⚠ 1 PHP fatal(s) in debug.log, top: "EventHydrator.php: Uncaught Error: Undefined constant …" ×1.
- community.extrachill.com — ⚠ 1 PHP fatal(s) in debug.log, top: "EventHydrator.php: …" ×1.
- shop.extrachill.com — ⚠ 1 PHP fatal(s) in debug.log, top: "EventHydrator.php: …" ×1.
… (×11, one per site)

There was exactly one fatal line in wp-content/debug.log (2026-09-18 12:17:46 UTC, a deploy-window transient from the data-machine-events v0.62.0 rollout, never repeated). It appeared on every site's row because:

  • WakeBriefingTask::getPhpFatals() (inc/Engine/AI/System/Tasks/WakeBriefingTask.php ~L462-590) resolves the log path from WP_DEBUG_LOG / WP_CONTENT_DIR . '/debug.log', which on a multisite is one file shared by every blog.
  • The per-site signal loop calls it once per site, so the same tail is scanned and reported N times with no de-duplication and no indication that the source is network-scoped.

Why it matters

The wake briefing is the first thing an agent reads. "11 sites each have a fatal" and "1 fatal happened somewhere on the network" call for different responses; the current output makes the former claim for the latter fact. On a site with a real per-site log (WP_DEBUG_LOG pointing to different files), the per-site loop is correct — the problem is only that the task doesn't know which case it's in.

Suggested fix (owning layer: this task, not the consumer)

  • Resolve the log path once; if is_multisite() and the path does not vary by blog, emit the fatal signal once in the network-wide section (alongside "stuck jobs" style network signals) and omit it from per-site rows, labelled as network-scoped.
  • Alternatively: keep per-site rows but attribute a fatal to a site only when the stack trace's site context can be determined (usually it cannot from debug.log), and otherwise fall back to the single network-scoped line.

Also observed

The per-site "stuck jobs" / "task types failing" cells for events.extrachill.com are correctly per-blog (they read c8c_7_datamachine_jobs), so the per-site loop itself is right — only the shared-file signal needs the scoping guard.

Surfaced during the Extra Chill S72 progress review.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions