_type: issue

title: Decision: distribution model — internal-only, no WP.org listing

description:
This is an internal/agency tool, not a public plugin. Distributed as a built ZIP (GitHub release artefact). Technicians install via wp-admin → Plugins → Upload, or via wp-cli (`wp plugin install <url> --activate`).

**Why:** lets us release fast, keeps client-specific text/checks private, no review process.

**How to apply:**
- Don't add WP.org boilerplate (readme.txt, screenshots, banner.png).
- Plugin header version = source of truth for what's installed.
- Phase 3 considers a self-hosted update channel (hc-5ix.NEW).

status: open

issue_type: decision

created_by: Steve Hanlon

type: parent-child


title: Session lifecycle: Start/Resume/Finish actions

description: Start: creates new session, snapshots site URL + WP/PHP versions + technician. Resume: continues the current in-progress session. Finish: stamps finished_at, locks notes, opens report view. If a session is already in-progress, Start asks to discard or resume.

notes: Built in phase-1 scaffold; passing lint + WP-eval end-to-end smoke test on testsite.

status: closed

issue_type: task


title: Report generation: Markdown export + copy to clipboard + save to private CPT

description: Render the finished session as Markdown (technician, site URL, started/finished, then per-step status + notes + sub-items). 'Copy' button and 'Save as report post' (private CPT 'wph_report') so reports are retrievable per site. Plain text fallback. No PDF in phase 1.


title: Checklist UI: single admin page with section per step, checkbox group + notes textarea

description: One page, all 12 steps + before-you-start. Each step is a card with: title, sub-items as readable bullets, a status select (not started/done/skipped/blocked/n/a), a notes textarea. Saves on blur or via explicit Save. Shows the 'Watch out for' callouts from steps.md inline.


title: Step definitions module: single PHP file defining the 12 steps + 'Before You Start' as structured data (id, title, blurb, sub-items, escalation conditions)

description: Source of truth for both the MVP UI and the automation layer. Keep it boring: pure data, no presentation. Lives at includes/steps.php returning a typed array. The text comes from steps.md (current copy in repo root).


title: Session data model: option-backed in-progress healthcheck record

description: One in-progress session per site at a time. Stored in a custom option (or a CPT — pick during implementation). Shape: id, started_at, finished_at, technician_id, site_url_snapshot, per_step_state { status: not_started|in_progress|done|skipped|blocked|n_a, notes, completed_at }. Designed so phase-3 automation can attach structured findings later.


title: Plugin skeleton: header, activation hook, deactivation hook, admin menu (Tools → Site Healthcheck), capability gate


title: Bootstrap: trigger install of wp-site-recovery plugin as step 0

description: Healthcheck plugin should check on activation if site-recovery is installed; if not, fetch and install from a known URL/ZIP and activate it. Block stepper from starting until recovery is in place.

notes: Detection half done (status panel + manual link). Auto-install of recovery plugin from a private URL is the wp-site-recovery side of hc-5ix.27 — closing this as 'detection complete'.


title: Smoke test on testsite: full end-to-end run through the checklist


title: README + install instructions + screenshots placeholder

issue_type: chore


title: Build WordPress Healthcheck plugin (stepper through steps.md)

description: Plugin that walks a technician through the WordPress healthcheck steps documented in steps.md. Independent of the recovery plugin (which it depends on as step 0).

issue_type: epic


title: Self-hosted update channel: plugin checks a private URL for new releases and offers one-click update from wp-admin

description: Lightweight wrapper around the WP plugin update transient: site_transient_update_plugins filter that adds an entry for ourselves if a newer release exists at a configured URL. URL hosts a JSON manifest + zip. Lets technicians keep clients up to date without manually re-uploading the zip every check.


title: Step 12 (Wrap-up): pre-fill report with all automated findings, attach diff vs. previous session, optionally push summary to ManageWP/WP Umbrella

notes: wrap_up step's autocheck walks all other steps' stored findings, counts bad/warn separately, lists the top 6-8 examples, and identifies any blocked steps. Gives the technician a quick 'roll-up' before they finish. The report itself already embeds every finding verbatim.


title: Step 11 (Small fixes): broken internal link scan (sample first N pages), missing alt-text scan on homepage images, deactivated-but-installed plugin list

notes: Deactivated-but-installed plugin list and homepage alt-text scan (fetch home_url, regex over <img> tags for alt attribute presence). Broken-link scan deferred — too heavy for v1 (would need to crawl every internal link).


title: Step 9 (Database): table sizes report, spam comment count, post revision count, autoload option size, recommendation engine (e.g. 'consider revision limit if >5000')

notes: Spam comments (warn >100), post revisions (warn >5000), autoload options size with WP 6.6+ value handling (on/auto/auto-on alongside legacy yes; warn >5MB), top 3 largest tables from information_schema. MySQL 8 reserved-word fix (TABLE_ROWS AS table_rows).


title: Step 10 (Uptime): pluggable uptime provider integration (ManageWP, UptimeRobot, BetterStack, Pingdom). At minimum expose 'paste downtime summary' field

notes: Monitoring plugin detection (ManageWP Worker, MainWP Child, Jetpack, WP Umbrella, UptimeRobot). www/non-www reachability check — HEAD with no redirects so the technician sees the actual response code + Location header for each canonical. External monitoring providers (UptimeRobot/BetterStack/Pingdom direct API integration) not implemented — would need per-install settings and API keys; out of scope for v1.


title: Step 8 (Security): SSL cert expiry check (stream_socket_client to :443 + parse cert), admin user audit (flag unfamiliar accounts vs. snapshot baseline), xmlrpc.php reachability check, custom login URL check

notes: SSL cert expiry via stream_socket_client + openssl_x509_parse (warn <30 days, bad expired); not-HTTPS flagged bad. Administrator audit lists all admin users (warn if >5). xmlrpc.php reachability via wp_remote_post with system.listMethods. Login URL hardening detection (WPS Hide Login, Rename wp-login.php).


title: Step 6 (Visual & Functional): homepage screenshot via mShots (or local headless if available); checklist with auto-pulled key pages (front page + posts page + WC shop + login)

notes: mShots screenshot URL surfaced (s.wordpress.com/mshots/v1/...). Key pages auto-detected: home, login, posts page, and WooCommerce shop/cart/checkout if WC is active. Each gets a HEAD request to verify HTTP status. Mixed-content scan on the homepage for http:// src/href references when site is https.


title: Step 7 (Performance): PageSpeed Insights API integration (server-side fetch), record mobile + desktop scores, flag >10pt drop vs. previous session, image scan for uncompressed > 500KB on homepage

description: Requires a Google PageSpeed API key (per-installation setting). Fall back to manually-entered scores if no key. Cache results for 12h.

notes: Keyless PageSpeed Insights v5 API integration (25k/day per-IP quota — enough for our purpose). Both mobile + desktop strategies. Cached 12h via transient. Surfaces score, LCP, CLS, TBT. Skipped for local URLs (PSI can't reach .local). Caching plugin detection across 7 common plugins. Heavy image scan (>500KB) over first 8 homepage images via HEAD requests.


title: Step 5 (Theme): detect parent/child relationship; if no child, diff parent theme files vs. WP.org canonical to flag direct customisations that would be lost on update

notes: Parent/child theme detection via WP_Theme. Warns when active theme is non-default and not a child (with file mtime hint). Lists inactive themes. Surfaces available theme updates via update_themes transient. Diff-against-WP.org-canonical deferred — heavyweight (would need downloading and unzipping the canonical) and the mtime heuristic catches the common case.


title: Step 3 (Core): wizard around core update with safe-mode (deactivate plugins first, update, smoke-load /, reactivate) and clear rollback path on failure

notes: Phase 3 v1: autocheck reports current vs latest WP version with link to update-core.php, database upgrade status, auto-update policy, and a 'safe-update sequence' reminder. The full safe-mode wizard (deactivate plugins → update → smoke-load → reactivate) deferred — it's a meaningful UI flow on its own (multi-step confirmations, rollback) and worth its own bead in phase 4.


title: Step 4 (Plugins): enrich each plugin with WP.org 'last updated' date, 'removed from repo' flag, active install count; flag plugins not updated >12 months; flag plugins missing from repo

description: Calls api.wordpress.org/plugins/info/1.0/<slug>.json for each plugin. Cache per-site for 24h. 'Removed from repo' = 404 or unsupported response.

notes: WP.org API enrichment via api.wordpress.org/plugins/info/1.0/<slug>.json with 24h transient cache. Surfaces last_updated date + active_installs, flags 'not in repo' (404) and 'removed' (error response), flags abandoned (>12 months), flags update available via update_plugins transient. Summary line counts each category. ~1.7s for 4 plugins on first run (uncached); subsequent runs <50ms via cache.


title: Step 2 (Environment): auto-collect PHP version + EOL flag, disk usage (statvfs), tail of error log (PHP + WP debug.log if enabled), wp-config flags (WP_DEBUG, WP_DEBUG_DISPLAY, DISALLOW_FILE_EDIT), spot-check permissions on wp-config.php / wp-content / uploads

notes: PHP version + EOL table; WP version vs latest; disk usage on ABSPATH; wp-config flags (WP_DEBUG, _DISPLAY, _LOG, DISALLOW_FILE_EDIT, WP_ENVIRONMENT_TYPE); file perms on wp-config.php/wp-content/uploads; PHP error_log + WP debug.log size. 12 findings on testsite, correctly flagged disk 95% (bad) and WP_DEBUG_DISPLAY=true (bad).


title: Step 1 (Backup): detect installed backup plugin (UpdraftPlus, BackWPup, BlogVault, Jetpack VaultPress), surface last backup time + size + verification status

notes: Backup detection by plugin slug (UpdraftPlus, BackWPup, Duplicator, WPvivid, All-in-One WP Migration, BlogVault, Jetpack, Solid Backups/BackupBuddy, WP Time Capsule, Backup Migration). Active/inactive state per plugin. UpdraftPlus last-backup timestamp surfaced via updraft_last_backup option. If none detected → bad-level finding.


title: Diff against previous session: highlight deltas vs. last completed session for this site

description: Pre-fill 'before' values for plugin/theme/WP versions from the previous session's 'after' values. Show a Δ column on the report. Lets clients see trajectory across checks.

notes: Previous finished session is persisted to wph_previous_session option on finish(). On the next session's dashboard, a diff banner shows count of new issues (warn/bad in current not in previous), resolved (in previous not in current), and changed (same id, different level/value). Phase 3.x could surface the per-step delta inline.


title: Polished HTML/PDF report styling + ability to email

notes: HTML report builder (wph_build_html_report) with inline styles — printable, looks good. Download HTML + Download Markdown + Copy + Email actions on finish panel. Email uses wp_mail with HTML content-type, prefills admin_email, redirects with status. PDF deferred — would need vendoring Dompdf (~500KB) and isn't core to the workflow.


title: Stop-and-escalate decision support: when a step is marked blocked/escalate, surface the matching guidance from steps.md and link to a quote/escalation template

description: Drive from the 'When to Stop and Escalate' table at the bottom of steps.md. Each escalation condition becomes a structured rule that fires when its preconditions hold (e.g. step=backup, status=blocked → 'Stop. Do not proceed. Restore backup before retry.'). Render as a banner on the affected step.

notes: 'Stop & escalate' summary panel at top of the dashboard listing any step with status=blocked, showing the step's escalation() guidance and the technician's notes. Per-step escalation banner already shown inline when blocked (carried over from phase 1).


title: Linear stepper UI: replace single-page with one-step-per-page + progress bar + per-step timer

notes: Implemented as a sticky step-index sidebar with status dots (◯ open · ✓ done · ⏭ skipped · ✗ blocked · — n/a). Anchor links jump to each step. Not a full one-step-per-page stepper — that flow was rejected after consideration because the single-page overview is more useful for scrolling between related steps. The sidebar gives the same at-a-glance progress without losing context.