site_doctor
Site Doctor helps you answer a simple question that gets harder as a Drupal
site ages: "is my site healthy — and is it getting better or worse?"
It runs read-only diagnostic checks (pending updates, configuration drift,
permission risks, dormant accounts, unused leftovers) and — unlike a one-time
audit — is built around a versioned, fingerprinted result schema so that
upcoming releases can record every run and show trends: what changed since
last week, what has been quietly degrading for months. It is not a
database/query monitor (see Site Health) and not a per-request developer
profiler (see Webprofiler) — Site Doctor tracks site-level diagnostic
findings over time.
Every result is a projection of the same structured schema: CLI commands on
both Drupal core's new dr CLI and Drush, with CI-friendly output and exit
codes for your deployment pipeline; machine-readable output that automation
and AI agents can consume; and a summary line on the status report (a full
dashboard is on the roadmap). Site Doctor never mutates site configuration
or content — the current release stores nothing at all; checks run on demand
and results live only in their output. There is no auto-fix: it diagnoses
and reports; fixing remains a deliberate human decision.
Features
Checks (available now, 1.0.0-alpha1):
- Pending updates (system) — pending database/post-deployment updates (code deployed ahead of the database, or a deploy script that swallowed a failure) and mismatched entity/field definitions — the chronic class that
drush updbdoes not fix. - Maintenance mode (system) — the site was left in maintenance mode.
- Permission risk audit (security) — permissions flagged "restrict access" granted to the anonymous role (Error) or to authenticated/other non-admin roles (Warning); admin roles are exempt by contract.
- Dormant privileged accounts (security) — active accounts holding admin or restricted-permission roles with no login past a configurable threshold (default 180 days); never-logged-in accounts included.
- Configuration drift classifier (config) — compares active configuration against your sync directory and frames each difference by consequence: what the next
config:importwould delete, revert, or re-create. Severity follows your declared workflow (sync,active, orauto): sync-disciplined sites get CI-gating Warnings; recipe-era and site-builder sites that treat active storage as the source of truth get a never-nagging Info inventory instead. Also aggregates all runtime config overrides (settings.php / modules) site-wide, reporting the overridden key paths — never the values, which is where secrets live. - Entropy checks (advisory — never gate CI) — unused image styles, orphaned view modes, roles with no users, unused text formats.
- Extensible by design: drop a check plugin in any module — site-specific business rules become first-class findings on every surface. See CONTRIBUTING.md and AGENTS.md in the repository.
Query commands (answers, not checks):
site-doctor:who-can PERMISSION— which roles hold a permission and through which path (explicit grant, admin role, user-1 super-user policy), with user counts — the questions ad-hoc reasoning (human or LLM) reliably gets wrong.site-doctor:role-diff ROLE_A ROLE_B— compare the explicit permission sets of two roles.- Roadmap: queries become pluggable alongside checks — define a site-specific lookup ("which orders reference this discontinued SKU?") as one Query plugin and it derives a CLI command on both dr and Drush and a typed MCP tool, giving AI agents safe, bounded answers about your site instead of improvised database queries.
Checks (roadmap):
- Dangling entity reference auditor (references to deleted targets, media pointing at missing files).
- Extension risk report (release age, security coverage, unused-module signals).
- Route latency sampler (production-safe p50/p95 per route, week-over-week regressions — zero external infrastructure).
- Runtime deprecation telemetry (which deprecated code paths actually execute in production, ranked by hit count — prioritize your next major upgrade by real impact).
- Content model export (Mermaid/JSON description of your bundles, fields, and references — documentation and agent context).
Surfaces:
- CLI on both Drupal core's
dr(11.4+) and Drush 13+ from one implementation:site-doctor:check [category] --format=table|json|junit|llm. Exit codes are a frozen contract: 0 ok/info, 1 warnings, 2 errors, 3 the diagnosis itself failed (a crashed check never aborts the run — the rest still report). --format=llm— self-describing, bounded output for AI agents: embedded severity semantics, truncation markers on long evidence, staleness fields on every result.- Status report summary line at /admin/reports/status.
- Results store, trends, and a dashboard at /admin/reports/site-doctor (roadmap, next release cycle).
- Tool API integration (roadmap): each check and query exposed as a tool so AI agents and MCP clients can query site health instead of guessing.
Use cases:
- Pre-deployment CI gate ("fail the pipeline on dangerous config drift"), post deploy verification ("did updates actually run?"), monthly maintenance review, upgrade planning, security/permission audits, handover audits of inherited sites, and giving AI agents accurate structured facts about the site.
- And the part only your own code can supply: site-specific checks encode your business rules ("every product needs a hero image", "this role must never gain that permission") as one small plugin class in your custom module, and it automatically gets every surface: both CLIs, all output formats, CI exit codes that can gate your deployments, and the upcoming trend history. Agencies can ship one internal check pack across every client site.
Post-Installation
Enable the module, then:
- Run
drush site-doctor:check(ordr site-doctor:checkon Drupal 11.4+) for the full diagnosis; a summary line also appears on the status report. - Declare your configuration workflow so drift severity matches your reality:
drush config:set site_doctor.settings config_workflow sync|active(defaultautoinfers it and says so in the result). - Optionally tune
dormant_account_days(default 180) the same way. There is no settings UI yet. - For CI: run
drush site-doctor:check --format=junitin your pipeline and gate on the exit code.
No content types, fields, front-end output, or database tables are created.
All checks are read-only.
Additional Requirements
None beyond Drupal core (Drupal 11, PHP 8.3+). Drush 13+ is optional — core's
dr CLI (11.4+) is fully supported. Individual checks degrade gracefully:
a check whose subject doesn't exist on your site (e.g. the image module is
uninstalled) reports itself as not applicable — distinct from a clean pass —
and the drift classifier works with or without a sync directory via the
workflow setting.
Recommended modules/libraries
Site Doctor deliberately does not duplicate established tools — it complements them and links to them from findings where relevant:
- Upgrade Status — static deprecation analysis (Site Doctor's runtime telemetry will tell you which of those findings matter in production).
- Security Review — security best-practice checklist (Site Doctor's security category covers what a checklist can't: reverse lookups, grant-path analysis, account dormancy).
- Linkchecker — external/content link checking (Site Doctor will cover entity-reference integrity only).
- Site Audit — use it today for one-shot scored audit reports; see also Similar projects below.
- Tool API / MCP Server — enables the agent-facing tool surface (roadmap).
Similar projects
- Site Audit — point-in-time static best-practice checks via Drush. Site Doctor differs in its design around recorded history/trends (in development), production runtime telemetry (roadmap), and results exposed to CI and AI agents (available now: severity-mapped exit codes, junit, and an agent-oriented output format).
- Healthcheck — similar plugin-based concept from the Drupal 8 era, including historical reports. Site Doctor is a Drupal 11-native take with runtime telemetry and an agent/automation surface.
- Webprofiler — per-request developer profiling: deep, dev-only, heavyweight. Site Doctor's roadmap latency sampler is the inverse instrument: production-safe 1-in-N sampling, p50/p95 per route trended over time. The sampler finds which route regressed; webprofiler dissects why, in dev.
- Site Health — database query monitoring (slow queries, per-statement statistics). Site Doctor is route- and site-level over time, not a query profiler.
- Monitoring — sensor integration with external monitoring stacks (Icinga, etc.). Site Doctor is self-contained with no external infrastructure.
- health_check / health_check_url and similar — uptime ping endpoints for load balancers; a different problem entirely.
Supporting this Module
Issues, reviews, and merge requests are welcome — the check plugin API is
designed so a new check is a small, self-contained contribution: one plugin
class implementing collect(), one kernel test extending the provided
CheckKernelTestBase, and it automatically appears on every surface.
Community Documentation
The README ships with the module: usage on both CLIs, CI integration with
exit-code semantics, configuration guide (including how to choose your
config workflow), and a writing-your-own-check guide. GitHub Actions
examples and a fuller tutorial are planned as the module matures.
AI-assisted development disclosure: this module is developed with AI
coding assistance under human direction and review. All code is
human-reviewed before commit; every check ships with kernel tests that
encode its expected behavior, and CI (phpcs, phpstan, phpunit, cspell,
code coverage) gates every merge request.