=== Understory Trace ===
Contributors: orchardgrovemedia
Tags: diagnostics, security, performance, audit, ai
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 0.10.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Server-side sight for Claude in Chrome: read-only WordPress diagnostics, a code & config audit, and a plugin vulnerability check — as clean JSON for an AI agent.

== Description ==

Claude in Chrome can see what the browser sees — the rendered DOM, network, console — but it is blind to the server: the PHP notices firing during a render, slow or duplicated SQL, which template or hook produced a broken widget, autoloaded-options bloat, object-cache hit rates, cron backlog, plugin conflicts, and what the theme's own code and the site's settings actually contain.

**Understory Trace** bridges that gap. It surfaces server- and WordPress-internal state as plain, machine-readable JSON — a `<script type="application/json">` block on the page (no shadow DOM) plus a REST API — so an AI browser agent can not only *diagnose* a slow page or a broken widget, but *audit* the whole site: read and evaluate the theme's source, review how each plugin is configured, judge the server-health posture, spot script conflicts, and cross-check the plugins against a known-vulnerability database.

The plugin is the **sight**, not the brain: it exposes clean, read-only facts and lets the AI do the evaluating. Read-only by design — it never changes site state. Heavy profiling runs only on demand, so normal traffic and public visitors are untouched. Everything is strictly gated to administrators, passes a redaction layer before it leaves the server, and every exposure surface can be switched off in a per-site audit-scope setting.

= Diagnose (runtime) =

* Database query profile: count, total time, slowest queries, duplicates, and the calling function (via SAVEQUERIES, on demand).
* Autoloaded-options bloat, object-cache backend + hit ratio, OPcache status, memory vs limit, and time-to-hook milestones.
* PHP errors/warnings/notices/deprecations captured during the request, tied to the block or widget that emitted them.
* Element-to-source map: front-end block/widget output is wrapped in invisible HTML-comment markers so a DOM region traces back to what produced it.
* Outbound HTTP timing, cron backlog with overdue flags, render-critical hook callbacks, and the enqueued script/style queue.
* A computed `flags` list per capture so problems surface at a glance, plus best-effort Query Monitor ingestion when QM is active.

= Audit (static) =

* **Theme code** — read the active theme's (and parent's) source, confined to the theme directory and scrubbed for hard-coded secrets, to evaluate it for security, correctness, performance, and hygiene.
* **Plugin settings** — a secret-safe view of any option: its shape (keys + types, no string values) by default, or actual values (still redacted) behind an explicit opt-in.
* **Server health** — debug-logging state, filesystem writability (a web-writable wp-config is flagged), free disk, HTTPS posture, auto-update config, and per-plugin update-available info.
* **Script conflicts** — the enqueued-asset dependency graph: missing dependencies, duplicate libraries, and jQuery posture.
* **Vulnerability check (opt-in)** — cross-reference the active plugins against the public WPVulnerability.com database and list any whose installed version has a known CVE.
* **Managed-host log deep-links** — on a WordKeeper host, deep-links to the access / error / WP-Cron logs, so a finding can be corroborated against the real host logs (including uncaught fatals a shutdown-based tool can't capture).

A companion Claude skill ships with the plugin, with playbooks for *this page is slow*, *this widget isn't rendering*, a full-site *deep-dive audit*, a *code & config audit* (including the vulnerability check), and a full **website best-practices audit** (SEO, structured data, Core Web Vitals, analytics, security headers, ad tech, links, accessibility, architecture) that produces a branded, sectioned **PDF report**.

= Privacy =

Data lives only in your own database, in a short-lived rolling buffer (newest ~25 captures, 30-minute TTL). **Nothing is sent anywhere by default.** The single exception is the optional **plugin vulnerability check**: only when you turn it on, it queries the public WPVulnerability.com database, sending plugin *slugs* (the public directory names — not your versions; the version match runs locally) and identifying itself as only the plugin and its version. Sensitive values are redacted before anything leaves the server, and every exposure surface can be disabled in the audit-scope settings. Uninstalling removes the table and all options.

== Installation ==

1. Upload the `understory-trace` folder to `/wp-content/plugins/`.
2. Activate it through the Plugins screen.
3. As an administrator, open **Tools → Understory Trace** and use the **Ask Claude** prompts — copy one and paste it into Claude in Chrome on the tab. (Advanced: drive the REST API directly; see `GET /wp-json/understory-trace/v1/schema` for the full protocol.)

== Changelog ==

= 0.10.1 =
* The "Ask Claude" prompts now name the site's own URL on the site-level prompts (full audit, theme review, vulnerability check, best-practices audit), so they're unambiguous wherever they're pasted; added a "Website best-practices audit → PDF" prompt.
* Report generation: bundled `skill/make-report.py` renders a filled report to a paginated PDF (headless-Chrome print + a page-number footer on every page after the cover), and the playbook documents capturing screenshots as embedded `data:` URIs.

= 0.10.0 =
* Website best-practices audit + PDF report. The companion skill gains a full front-end & stack audit playbook — SEO & indexation, structured data, Core Web Vitals / performance, analytics & conversion tracking, security headers & CVEs, ad tech, links & crawl health, accessibility, and architecture — run from the browser with the plugin as the server-side corroborator, plus a branded, print-ready PDF report template (cover, executive summary, per-category sections with screenshots, Critical / Warnings / Opportunities). See `skill/best-practices-audit.md` and `skill/report-template.html`.

= 0.9.0 =
* "Ask Claude" panel on the Tools → Understory Trace page: ready-made, copy-to-clipboard prompts — a full site audit, a slow page, a broken widget, a theme-code review, and a vulnerability check — so you can drive the plugin from Claude in Chrome without knowing the protocol. Open Claude in Chrome on the tab, copy a prompt, paste it in.

= 0.8.0 =
* Cross-plugin vulnerability check (opt-in). `GET /vulnerabilities` cross-references the active plugins against the free, no-key WPVulnerability.com community database and reports any whose INSTALLED version has a known CVE — with CVE ids, CVSS score/severity, and the fixed-in version. This is the one feature that makes an outbound request, so it is off by default (audit-scope toggle `vuln_check`); it sends plugin slugs only (not versions — the version match runs locally), caches results for 12 hours, and identifies itself as only the plugin + version. Companion skill gains a vulnerability-check step in the code & config audit.

= 0.7.1 =
* Script-conflict analysis now walks only the transitive closure of the actually-enqueued assets (not every registered script), so `missing_deps` reports only dependencies that can really break the page — no more noise from the hundreds of registered-but-unused editor scripts. Duplicate-library detection is now a curated known-library scan (jQuery UI, Swiper, Slick, Bootstrap, React, …) keyed on source URLs, instead of grouping unrelated files by generic basenames like index.js/editor.js.

= 0.7.0 =
* Audit platform, phase B — "evaluate the settings". New read-only endpoints expose plugin/site options for a config review with a secret-safe model: `GET /options` lists option names + metadata (no values); `GET /option?name=X` shows one option's shape — keys and value types, with booleans/numbers shown but every string hidden — so a secret can never leak by default. `&reveal=1` returns actual values, but only when the "settings values" opt-in is on, and even then values are masked by sensitive-key name AND by a value-shape heuristic (`looks_secret`).
* Script-conflict analysis: captures now include an enqueued-asset conflict report — missing dependencies (a real "widget didn't load" cause), possible duplicate libraries, and jQuery posture.
* Audit-scope settings: a new panel (and `GET /status.scope`) with least-exposure toggles — theme code, plugin settings (shape), plugin settings values, server health, script conflicts. A disabled surface's route returns 403. Plugin-settings-value reveal is off by default.
* The settings secret model was verified by a multi-agent adversarial review; `looks_secret()` is pinned by tests/redact_harness.php.

= 0.6.2 =
* Redaction: slash-namespaced identifiers (WordPress block types like `core/paragraph`, and namespaced hooks like `vendor/system/thing`) are no longer over-masked in theme-source reads — a lone `/` inside a readable identifier is namespacing, not a base64 secret. Real base64 tokens and keys are still masked.

= 0.6.1 =
* Fixed: the new environment `health` block called `disk_free_space()`, which managed hosts (e.g. WordKeeper) commonly disable via `disable_functions` — and `@` does not suppress the resulting fatal, so the whole environment section came back as an error on those hosts. All such calls (`disk_free_space`, `php_uname`, `getmypid`) are now gated on `function_exists()`.

= 0.6.0 =
* Audit platform, phase A — "evaluate the code & config". New read-only endpoints expose the active theme's source for review: `GET /theme` lists each theme root's files and `GET /theme/file` returns one file's contents, confined to the theme directory (realpath-checked against traversal and symlink escape on both the request path and the resolved target, text/code files only, size-capped) and best-effort scrubbed for hard-coded secrets.
* Hardened the source-code secret scrubber (defense-in-depth, not a guarantee): masks quoted secrets by segment-matched name (SECRET_KEY, apiKey, pw…), known vendor token prefixes (Stripe/WooCommerce, AWS, GitHub, Google, SendGrid, GitLab, Slack), JWTs and Bearer tokens, URL-query secrets, PEM private keys, and heredoc/nowdoc bodies — while keeping ordinary identifiers legible. Verified by a multi-agent adversarial review and pinned by tests/redact_harness.php.
* Environment data gains a `health` block — debug-logging state, filesystem writability (a web-writable wp-config is flagged), free disk, HTTPS posture, and auto-update configuration — plus per-plugin update-available info and an `updates_pending` count.
* Companion skill: added Playbook D, a code & configuration audit protocol (read the theme source and health posture, evaluate for security/correctness/performance/hygiene, report alongside the runtime audit).

= 0.5.0 =
* Managed-host detection: on a WordKeeper host, the admin page and the environment data deep-link to the host's access/error/WP-Cron logs, so a diagnosis can be cross-checked against the real host logs (including uncaught fatals the plugin can't capture). Filterable via `utrace_host_manager`.
* Companion skill: added a full-site deep-dive audit playbook.

= 0.4.2 =
* Query Monitor ingestion now works with Query Monitor 4.x — reads collector data via QM's public get_data() API (QM 4.x moved data into protected QM_Data objects) after ensuring QM has processed.

= 0.4.1 =
* Admin page icon now uses the Understory Trace 🌿 logo, matching the branding.

= 0.4.0 =
* Captures now include a computed `flags` list (threshold warnings for PHP errors, slow requests, duplicate queries, autoload bloat, memory pressure, overdue cron, missing object cache, slow HTTP, and OPcache) so problems surface at a glance.
* Duplicate queries now report their total time and calling function.
* Pin a capture to keep it past the TTL, and download any capture as JSON, from the admin status page.
* Optional full-fidelity query capture: one-click install of a managed must-use drop-in that records the earliest bootstrap queries a normal plugin can't (with a manual fallback when mu-plugins isn't writable).
* Admin status page and GET /status now report auto-prune (WP-Cron) health and full-fidelity state.
* Admin status page restyled to the Orchard Grove Media house style (branded header, main + sidebar layout with an "At a glance" panel).

= 0.3.2 =
* Capture buffer now self-prunes on a scheduled WP-Cron event (every 10 minutes), so expired captures are removed even when profiling is never armed.
* Added a "Clear captures" button to the admin status page to empty the buffer on demand.

= 0.3.1 =
* Verified end-to-end on a live production-scale site. Corrected the plugin homepage URL to understorytrace.com.

= 0.3.0 =
* Phase 2: admin status page (Orchard Grove Media design system) with connection details, endpoint reference, and the recent-capture buffer; companion Claude skill with slow-page and broken-widget playbooks; Query Monitor ingestion (bonus corroborating data when QM is active); documentation.

= 0.2.0 =
* Phase 1b: front-end element-to-source mapping. While profiling, block and widget output is wrapped in invisible HTML-comment markers and a render map is captured (type, name, byte size, newly-emitted PHP errors) so a DOM region can be traced back to the block/widget/shortcode that produced it.

= 0.1.0 =
* Initial build (Phase 1): capture pipeline, signed on-demand profiling trigger, admin-bar toggle, in-page JSON bridge, REST API (schema/status/env/captures/capture), redaction layer, and core collectors (environment, request runtime, database + autoload, HTTP, cron, hooks).
