Commit Graph

12 Commits

Author SHA1 Message Date
8ff3a6ec31 Fix step status+notes save (forms were nested in HTML)
The step card's save form wrapped the entire card, including the
autocheck 'Run checks' button and per-step extras like the email
'Send' form — those are also <form> elements. Nested forms are
invalid HTML; browsers silently drop the outer form's submit when
they see an inner one.

So clicking 'Save step' was effectively a no-op: the POST to
wph_save_step never reached the server, and the status reverted to
'not started' on reload. The bug had been there since the autocheck
panel was introduced in v0.3 of the healthcheck.

Restructured the step card as a <div> wrapper containing three
siblings: (1) static content (title, blurb, sub-items, watch-outs,
escalation), (2) the autocheck panel + step render_extra (each with
their own forms), (3) the save form. No nesting anywhere.

Verified end-to-end on testsite: step status and notes now persist
across page loads. The email step (which has 3 sibling forms — refresh
checks, send test, save) also renders without nesting.
2026-06-12 10:29:33 +01:00
b9dad0163b Sidebar: brighter status dots so 'done' clearly reads as green
The old #1a8917 green and 0.6rem dots were subtle enough on some
displays to read as dark grey. Bumping to a vivid #16a34a, 0.75rem
diameter, with a faint inset shadow for crispness on light
backgrounds. Other states adjusted to match the same brighter palette
(amber #f59e0b skipped, red #dc2626 blocked, neutral #9ca3af n/a).

Also dims the link text to a dark green for done rows via :has()
so the whole line reads as 'this is complete'.
2026-06-12 10:25:56 +01:00
fdca9c3079 Theme step: identify removal candidates explicitly
Replaces the 'inactive themes count' finding with a clearer breakdown:

Keep set (each gets a 'Keep — <why>' row):
- The active theme (always)
- The parent of the active theme (if a child theme is in use and
  the parent exists on disk)
- The newest Twenty* default installed (as a fallback we can swap
  to if the active theme breaks during work)

Removal candidates (one row per inactive theme not in the keep set):
- 'Candidate' rows for the technician to walk down and remove
- Summary line warns at >3 candidates
- 'none' ok row if every installed theme is a keeper

Smoke-tested on testsite with three configurations:
- Default theme active, no child: keep active + Twenty Twenty-Five
  fallback; one removal candidate.
- Cluttered (Astra + Hello Elementor + extra Twenty* installed):
  same keepers, 4 candidates surfaced.
- Astra active (custom, no child): keep Astra + Twenty Twenty-Five
  fallback; 4 candidates including any unused Twenty* and Hello
  Elementor.
2026-06-12 10:22:29 +01:00
1cd17b5bf4 Add .gitattributes to exclude dev files from archive
Same as the matching change in wp-site-recovery — excludes .beads/,
.claude/, AGENTS.md, CLAUDE.md, .gitignore, .gitattributes itself,
and steps.md (technician guide, not used at runtime) from any release
archive.
2026-06-12 10:12:12 +01:00
8ceb756404 Recovery plugin: folder-agnostic detection + one-click install from Gitea
Detection (recovery-bootstrap.php):
- Match on plugin Name + Author instead of hard-coded folder slug, so
  the recovery plugin is found regardless of whether it was unpacked
  as site-recovery/, wp-site-recovery/, or anything else.

One-click install (recovery-installer.php — new):
- Pulls site-recovery from a private Gitea repo via the standard archive
  endpoint with token auth.
- Ref resolution order: latest release → latest tag → main branch HEAD.
  Lets us tag pinned releases in Gitea later without changing code.
- upgrader_source_selection filter forces the unpacked folder name to
  'site-recovery' regardless of the gitea wrapper-folder suffix.
- Config from constants in wp-config.php (WPH_GITEA_HOST/OWNER/REPO/TOKEN)
  beats DB option storage. Constants are visually locked in the settings
  UI so admins can see they're inherited.

Settings page (hidden submenu, reachable at Tools → Site Healthcheck
→ 'Configure gitea source'):
- Host / Owner / Repo / Token fields
- Inline 'Install now' button when configured + plugin not installed

Bootstrap status panel:
- Shows the recovery plugin's actual file path when active
- 'Install from gitea (latest)' button when configured + missing
- 'Configure gitea source' button when not configured + missing

Install handler shows a success message via transient on the main
healthcheck page after a successful install + activate.
2026-06-12 09:43:55 +01:00
79cb06e705 Email step: append SMTP debug trace to notes (and thus the report)
When debug capture is requested, the trace is now also appended to the
step's notes textarea with a clear --- SMTP debug trace ... --- header
and timestamp. This means:

- The technician can edit/trim the trace before finishing the session.
- It flows naturally into the Markdown + HTML report via the existing
  notes-in-report rendering — no special-casing needed.
- Pre-existing notes are preserved (appended to, not overwritten).
- Status is preserved.
- The collapsible details block on the step card still shows the raw
  capture for quick reference.
2026-06-12 08:18:44 +01:00
9786f4e405 Email step: optional PHPMailer SMTPDebug capture
Checkbox on the send-test form turns on PHPMailer SMTPDebug=2 for one
send only. A Debugoutput callback captures the wire conversation;
hook is removed immediately after wp_mail returns.

AUTH credentials redacted: lines containing 'AUTH' or 16+ char base64
strings get replaced. Trace capped at 200 lines and stashed on the
session. Rendered as a collapsible <details> block on the step card.

Transport type (mail/smtp/etc., read from PHPMailer->Mailer) surfaced
in the finding detail so the technician knows whether a trace will
contain useful SMTP traffic — only the smtp transport emits any.
2026-06-12 08:14:33 +01:00
0052005de1 Email delivery test step + step-form extension point
Demonstrates the drop-in pattern: adding a step with a form is a single
new file under includes/steps/, plus one small extension to the base
abstraction.

WPH_Step gains:
- render_extra($session_state) — emit extra HTML inside the step card
- handle_action($name, $input) — handle a step-specific POST and
  return a finding to record

New generic admin-post handler wph_step_action routes form submissions
to the matching step's handle_action() with nonce verification.

The email step (includes/steps/115-email.php):
- Detects 7 known SMTP plugins, surfaces default From address
- Renders a To: input prefilled with the current admin's email
- Sends via wp_mail() with wp_mail_failed capture so failures show the
  underlying error
- Records the outcome as a 'last_send' finding so it appears on the
  step card, in the summary, and in the downloadable report
2026-06-11 18:45:47 +01:00
cf3007ec37 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.
2026-06-11 16:13:15 +01:00
0d51fc3b59 Phase 3 v1: autocheck framework + six step automations
Infrastructure:
- WPH_Step::autocheck($session_state) returns an array of findings
  shaped {id, level: ok/warn/bad/info, label, value, detail}.
- WPH_Session stores results keyed by step id (persisted in the option-
  backed session).
- WPH_Step::has_autocheck() reflection check so the UI only renders the
  panel for steps that implement automation.
- 'Run checks' / 'Refresh' button per step, admin-post handler runs
  autocheck() and stashes the result on the session.
- Findings rendered as a coloured table on the step card; included
  verbatim in the Markdown report with status icons.

Step automations implemented:
- Step 1 (Backup): detection of 11 known backup plugins by slug;
  active/inactive state; UpdraftPlus last-backup timestamp.
- Step 2 (Environment): PHP version + EOL, WP version vs latest, disk
  usage, wp-config flags, file perms on wp-config/wp-content/uploads,
  error-log sizes.
- Step 4 (Plugins): WP.org API enrichment with 24h transient cache —
  last_updated, active_installs, abandonment flag, removed-from-repo
  flag, update-available count. Summary line at the top.
- Step 8 (Security): SSL cert expiry via stream_socket_client +
  openssl_x509_parse, administrator audit, xmlrpc reachability, login
  URL hardening detection.
- Step 9 (Database): spam comments, post revisions, autoload size (WP
  6.6+ value handling), top 3 largest tables.
- Step 11 (Small fixes): deactivated-but-installed plugin list,
  homepage alt-text scan.

Smoke-tested on testsite — all six steps return findings with
correctly-classified levels. Report regenerated with automated findings
section.
2026-06-11 16:02:34 +01:00
8de7cad0de Phase 1 MVP: drop-in step registry + session + Markdown report
Plugin skeleton, drop-in step registry, option-backed session, single-page
checklist UI, downloadable Markdown report. Steps live as one file each
under includes/steps/ — adding/removing one is a single file change.
Step IDs are stable strings so renaming files preserves session data.

Architecture (hc-5ix.3): WPH_Steps singleton globs includes/steps/*.php,
natsort-orders by filename, requires each file (which returns a WPH_Step
instance), then applies a 'wph_steps' filter so installs can drop steps.

Session (hc-5ix.4): option-backed (per decision — plugin is installed
per-engagement, so DB-resident history would be lost on uninstall).
Single in-progress session per site; finished sessions render a report
that the user downloads/copies.

Recovery bootstrap (hc-5ix.1): detects whether wp-site-recovery is
installed + active, surfaces state on the start panel and in every
active session. Manual install for now; private update channel deferred
to hc-5ix.27.

Smoke-tested on testsite: registry discovery (13 steps in correct order),
start → update_step → progress count → finish → 8KB Markdown report →
discard cycle.
2026-06-11 15:49:29 +01:00
d0d4d433d8 bd init: initialize beads issue tracking 2026-06-11 12:26:23 +01:00