Phase 3 v2: all step automations + cross-cutting UI

Step automations (six more):
- Step 3 (Core): current vs latest WP version, db upgrade flag, auto-
  update policy, safe-update sequence reminder.
- Step 5 (Theme): parent/child detection, customisation warning when
  non-default theme without child, theme update available, inactive
  theme list.
- Step 6 (Visual): mShots screenshot URL, key-page HEAD checks (home,
  login, posts page, WC shop/cart/checkout), mixed-content scan.
- Step 7 (Performance): keyless PageSpeed Insights v5 API (mobile +
  desktop, cached 12h, skipped on .local), caching plugin detection,
  heavy-image scan (>500KB).
- Step 10 (Uptime): monitoring plugin detection (ManageWP, MainWP,
  Jetpack, WP Umbrella, UptimeRobot), www/non-www canonical check.
- Step 12 (Wrap-up): cross-step rollup — bad/warn counts, blocked
  steps, top examples for the technician's final glance.

Cross-cutting:
- Sticky step-index sidebar with status dots per step (the linear-
  stepper alternative that keeps the overview).
- 'Stop & escalate' summary card at top listing blocked steps with
  escalation guidance and notes.
- Previous-session snapshot stored on finish; diff banner on the next
  session shows new/resolved/changed counts.
- HTML report builder (printable, inline-styled). Download HTML,
  Download Markdown, Copy, and Email actions on the finish panel.
  Email uses wp_mail with text/html.

Smoke-tested on testsite: all 12 steps return findings (5/9/4 by level
on a fresh local install), admin page renders with all UI markers,
HTML report is 26KB, Markdown report is 13KB, prev-session diff banner
appears on second session.

Deferred:
- hc-5ix.27 self-hosted update channel — needs hosting infra.
- Full PDF report — would need vendoring Dompdf.
- Step 3 safe-mode update wizard — worth its own bead.
This commit is contained in:
2026-06-11 16:13:15 +01:00
parent 0d51fc3b59
commit cf3007ec37
10 changed files with 706 additions and 20 deletions

View File

@@ -55,6 +55,13 @@ final class WPH_Session {
delete_option(WPH_OPT_SESSION);
}
/** The previous finished session (for diffing). Stored on finish(). */
public static function previous(): ?self {
$raw = get_option('wph_previous_session');
if (!is_array($raw) || empty($raw['id'])) return null;
return new self($raw);
}
public function id(): string { return (string) $this->data['id']; }
public function started_at(): int { return (int) $this->data['started_at']; }
public function finished_at(): ?int { return isset($this->data['finished_at']) ? (int) $this->data['finished_at'] : null; }
@@ -88,6 +95,8 @@ final class WPH_Session {
public function finish(): void {
$this->data['finished_at'] = time();
update_option(WPH_OPT_SESSION, $this->data, false);
// Snapshot for next-session diff. One slot, overwritten each finish.
update_option('wph_previous_session', $this->data, false);
}
/** Store the result of running autocheck() on a step. */