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.
What happened
Today's composed WAKE.md (2026-09-18 18:01 GMT) on the Extra Chill network listed eleven separate lines:
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 fromWP_DEBUG_LOG/WP_CONTENT_DIR . '/debug.log', which on a multisite is one file shared by every blog.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_LOGpointing 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)
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.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.