Skip to content

Diagnostics — Improvement & Growth Plan

Package: capell-app/diagnostics · Kind: package · Tier: premium · Product group: Capell Operations · Bundle: operations · Status: Draft

Diagnostics is the operations/observability package for Capell. It surfaces five Filament admin pages (DiagnosticsPage, CommandPalettePage, SystemHealthPage, QueueHealthPage, PermissionAuditPage) plus eleven dashboard health widgets (cache, content, content-graph, registry, migrations, packages, config-drift, setup, alerts, Tailwind, site). Surfaces declared in capell.json are ["admin", "console"]. The heavy lifting lives in Actions: BuildPackagesInstalledAction, BuildInfrastructureStatusAction (cache/queue/mail/storage), BuildPublicOutputSafetyReportAction, InspectPackageOwnershipAction, BuildConfigDriftAction, BuildRegistryHealthAction, BuildSetupHealthAction, BuildTailwindBuildStatusAction, plus the command-palette trio (DiscoverCommandPaletteCommandsAction, ValidateCommandPaletteParametersAction, ExecuteCommandPaletteCommandAction). Models/tables: CommandPaletteRun (command_palette_runs) and QueueMonitor/FailedJob/PendingQueueJob (queue_monitors, the latter binding over croustibat/filament-jobs-monitor). Deps: capell-app/admin, capell-app/core, capell-app/html-cache, croustibat/filament-jobs-monitor, lorisleiva/laravel-actions, spatie/laravel-data.

Current marketplace summary: “A single operations cockpit for Capell that surfaces system health, queue activity, config drift, permission audits, and per-package install health — with a guarded command palette for trusted capell:* operations.” The manifest now declares the extension card plus six committed runner PNGs for the diagnostics dashboard, admin health widgets, system health page, queue health page, permission audit page, and command palette page. Dark variants remain committed in docs/screenshots/ as screenshot-contract evidence but are not all duplicated into marketplace media.

Health-check aggregation mechanism (critical to understand): Every Capell package declares a healthChecks[] array in its capell.json (key/label/class/severity/surface). Diagnostics now has two layers for these declarations: BuildPackagesInstalledAction reflects declared classes and classifies them as implemented, stub, or broken for the dashboard, while RunExtensionHealthChecksAction executes runnable checks and summarizes pass/fail output for the capell:diagnostics:health command. Severity scoring, historical persistence, and alerting remain separate roadmap depth.

  • Stop equating “health check count” with health. BuildPackagesInstalledAction reports healthCheckCount from count($manifest['healthChecks']) — a package with 4 stub checks looks identical to one with 4 real checks. Change the column to report runnable vs declared (e.g. 2/4 implemented), computed by reflecting each declared class (see §3). — surfaces the false-green directly in the existing table — src/Actions/Dashboard/BuildPackagesInstalledAction.php:246 — M
  • Done/Shipped: Make DiagnosticsHealthCheck a real check. The diagnostics package now verifies its declared package catalog, manifest metadata, system-health widget/page, and queue-health assertions. Operator-facing labels/messages/remediations are translated, and focused tests prove each manifest key maps to one runnable assertion. — src/Health/DiagnosticsHealthCheck.php, resources/lang/en/package.php, tests/Feature/Health/DiagnosticsHealthCheckTest.php — M
  • Done/Shipped: Addressable assertions behind shared DiagnosticsHealthCheck class. All four manifest entries can now be run independently by key (diagnostics.package-catalog, .manifest-health, .system-health-widgets, .queue-health) and unknown keys return no assertions. — capell.json (healthChecks), src/Health/DiagnosticsHealthCheck.php, tests/Feature/Health/DiagnosticsHealthCheckTest.php — M
  • Tighten the capell:* palette danger heuristic. CapellArtisanPaletteCommandProvider::dangerForCommand() classifies risk by substring (demo/install/setup/upgrade → Dangerous; clear/cache/publish → Confirm; everything else Safe). A destructive command without those tokens defaults to Safe with no confirmation. Replace the denylist heuristic with an explicit per-command risk map / allowlist. — src/Palette/CapellArtisanPaletteCommandProvider.php — M
  • SystemHealthPage is super-admin only; canAccess() swallows role errors as false. The BadMethodCallException catch silently denies access if the user model lacks hasRole. Fine for safety, but it means a misconfigured role system shows an empty page with no signal. Log/annotate the denial reason for operators. — src/Filament/Pages/SystemHealthPage.php — S
  • Config drift ignores value differences by design but never says so in the UI contract. BuildConfigDriftAction::diffArrays() only emits missing/stale keys and deliberately skips value diffs (documented in the docblock). Operators may expect value drift. Add a UI note or an opt-in value-diff mode. — src/Actions/Dashboard/BuildConfigDriftAction.php — S
  • KNOWN_PACKAGES is a hardcoded const map that will rot. BuildPackagesInstalledAction::KNOWN_PACKAGES hardcodes docs URLs/config names for a subset of packages and falls back to manifest scanning for the rest. As packages move repos the hardcoded URLs drift. Derive everything from capell.json and drop the const. — src/Actions/Dashboard/BuildPackagesInstalledAction.php — M
  • Infrastructure status thresholds are hardcoded. BuildInfrastructureStatusAction flags array/log mailers and array/null cache as warning. Reasonable, but there is no config to declare “this env is allowed to use log mail.” Make the acceptable-driver set configurable via config/capell-diagnostics.php. — src/Actions/DashboardReports/BuildInfrastructureStatusAction.php — S

Tied to declared capabilities[]: diagnostics, diagnostics-admin, diagnostics-console, diagnostics-cross-package-install-health, diagnostics-public-output-safety, diagnostics-infrastructure-status, diagnostics-package-ownership.

  • Done/Shipped: Stub-health-check detection across packages. BuildPackagesInstalledAction now classifies declared package health checks as implemented, stub, or broken, and PackagesInstalledData exposes suite-wide declared/implemented/stub/broken totals. The packages-installed widget surfaces a translated suite rollup above the package table, and fixture coverage proves the aggregate across multiple manifests. This turns a false-green dashboard into an honest one and is a compelling selling point (“know which of your extensions actually self-test”).
  • Done/Shipped: executable health runner and console command. RunExtensionHealthChecksAction resolves declared health-check classes, classifies implemented/stub/broken declarations, executes runnable checks, captures pass/fail results, and degrades gracefully when classes are missing or throw. RunDiagnosticsHealthCommand exposes this through capell:diagnostics:health with table, JSON, CSV, and strict CI output that fails when declarations are stubbed, and the manifest wires it as the package doctor command.
  • Done/Shipped: severity rollup / single health score. Executed extension health reports now expose overallStatus, healthScore, and worstSeverity, with JSON and CSV exports carrying those fields. The score penalizes failed/broken critical checks more heavily than warnings and keeps stub declarations visible as degraded health rather than false-green output.
  • Shipped 2026-06-07: health-check results persist to snapshots with command trend output. diagnostics_health_snapshots stores each capell:diagnostics:health run’s status, score, severity, counts, and per-check payload. The command builds a trend against the latest previous snapshot before recording the current run, includes previous status/score/delta in JSON output, and prints the previous snapshot summary in table mode. Scheduled execution remains future depth. — database/migrations/2026_06_07_000001_create_diagnostics_health_snapshots_table.php, src/Models/DiagnosticsHealthSnapshot.php, src/Actions/Health/RecordExtensionHealthReportAction.php, src/Actions/Health/BuildExtensionHealthTrendAction.php, src/Console/Commands/RunDiagnosticsHealthCommand.php
  • Alerting / notifications. No mail/Slack/webhook notification when a critical check fails. Given BuildInfrastructureStatusAction already classifies error/warning, wiring a notifier is low-friction and high-value for an ops package.
  • Done/Shipped: support-friendly health snapshot exports. capell:diagnostics:health supports JSON and CSV output. ExportExtensionHealthReportCsvAction writes a summary row plus per-check rows with package, key, severity, implementation status, pass/fail state, and message for support tickets or external monitoring ingestion.
  • Env / system info panel. No PHP version, extension list, OPcache status, Laravel/Filament versions, disk free, queue worker liveness. BuildInfrastructureStatusAction checks config presence but not runtime liveness (e.g. can it actually write to the storage disk, can it ping the cache store). Table-stakes for “system health.”
  • Queue worker liveness / oldest-pending age. QueueHealthPage shows monitor history + failed/pending jobs, but no “is a worker alive” heartbeat or “oldest pending job age” alarm — the metrics operators actually page on.
  • Done/Shipped: false-green package health counts are now visible. Declared checks are reflected and classified as implemented, stub, or broken per package, with suite-wide totals surfaced in the packages widget. The dashboard still does not execute every health check; execution remains a Next-row health runner/command. src/Actions/Dashboard/BuildPackagesInstalledAction.php, resources/views/widgets/packages-installed.blade.php.
  • Command palette can execute non-allowlisted destructive Artisan commands. CapellArtisanPaletteCommandProvider enumerates all capell:* commands and assigns risk by substring. capell:install --fresh=force (which the Capell skill explicitly flags as destructive) is gated only because the name contains install; any destructive command lacking the magic substrings defaults to CommandPaletteDanger::Safe and runs without confirmation. Authorization exists (ExecuteCommandPaletteCommandAction::authorizedCommand checks a per-command Gate ability palette.run.<name>), but the abilities are auto-derived, so a permission can be granted broadly. Risk classification should be an explicit allowlist, not a denylist heuristic. src/Palette/CapellArtisanPaletteCommandProvider.php, src/Actions/CommandPalette/ExecuteCommandPaletteCommandAction.php.
  • Secret/info leakage in palette output and ownership/drift reports. ExecuteCommandPaletteCommandAction::runArtisanCommand() captures raw Artisan::output() (truncated to 4000 chars) and persists it to command_palette_runs.output. Commands like config:show or env-adjacent tooling could write secrets into a DB row that lower-privileged admins might later read. Diagnostics output (config-drift values via BuildConfigDriftAction::represent(), package paths in InspectPackageOwnershipAction) also exposes internal structure — acceptable for super-admin only, but there is no redaction layer and SystemHealthPage is the only page hard-gated to super-admin; the palette/ownership pages should be audited for the same gate. Per Capell public-output-safety rules, none of this is public-facing, but stored secrets are still a leak vector. src/Actions/CommandPalette/ExecuteCommandPaletteCommandAction.php, src/Actions/Dashboard/BuildConfigDriftAction.php.
  • Shipped 2026-06-06: expensive diagnostics scans are cached behind the diagnostics tag. BuildConfigDriftAction, BuildPublicOutputSafetyReportAction, and InspectPackageOwnershipAction now use DiagnosticsSnapshotCache with a configurable TTL and tag fallback handling, so package/config filesystem scans are not repeated on every admin render. Scheduled history/trends remain separate roadmap depth. — src/Support/DiagnosticsSnapshotCache.php, src/Actions/Dashboard/BuildConfigDriftAction.php, src/Actions/DashboardReports/BuildPublicOutputSafetyReportAction.php, src/Actions/InspectPackageOwnershipAction.php
  • Shipped 2026-06-06: console surface is implemented. capell:diagnostics:health now runs the executable extension health report and supports JSON/CSV output. Scheduled snapshots remain a separate history/trends feature.
  • Test gaps. 35 test files / ~3,299 lines — solid breadth on individual Actions/widgets and QueueHealthPageTest (394 lines). Diagnostics now covers its own declared healthChecks key-to-assertion mapping, explicit command palette risk mapping, command output redaction, and suite-wide stub/broken detector aggregation. Remaining gap: broader executable health runner coverage. tests/Unit/ManifestRequirementsTest.php.
  • i18n. Action-produced strings are translated via capell-diagnostics::package.* (137-line resources/lang/en/package.php) — good. But BuildPackagesInstalledAction::KNOWN_PACKAGES embeds English-only nothing-translatable docs URLs, and Str::headline() is used to label Artisan commands in CapellArtisanPaletteCommandProvider (untranslatable, English word-splitting). Acceptable for a dev tool, but worth noting.
  • Shipped 2026-06-06: manifest/media mismatch closed. marketplace.screenshots now lists the extension card plus six product PNGs from docs/screenshots/ for the dashboard, health widgets, system health, queue health, permission audit, and command palette surfaces.

Critique. The composer description and manifest summary now lead with the operations-cockpit outcome and the cross-package health angle. The marketplace gallery also promotes the strongest six product PNGs instead of only the extension card. Remaining selling depth should focus on live health execution, severity score, history, and alerting rather than more metadata cleanup.

Improved 1-sentence summary: “A single operations cockpit for Capell that surfaces system health, queue activity, config drift, permission audits, and per-package install health — with a guarded command palette for trusted capell:* operations.”

Improved 3–4 sentence description: “Diagnostics gives Capell operators one place to answer ‘is everything healthy?’ It rolls up cache, queue, mail, and storage status, config drift, migration state, registry and setup health, and Tailwind build status into dashboard widgets, and adds dedicated pages for Queue Operations (failed/pending jobs and history), permission auditing, and package-ownership inspection. A secure, audited command palette lets developers discover and run trusted capell:* Artisan operations with per-command authorization and confirmation gating. Built for super-admins and developers who need fast, read-only visibility into a running Capell deployment without SSH.”

Media gaps. The six primary product screens are wired into marketplace.screenshots with captions. Add a short hero GIF of the command palette running a safe command if animated marketplace media becomes part of certification.

Pricing / tier / bundle positioning. Currently tier: premium, bundle: operations, proposedLicense: paid, requestedCertification: first-party, supportPolicy: priority. Appropriate — this is an operator/developer tool, not a content feature, so premium/paid is defensible. To justify “premium” against table-stakes diagnostics, ship the differentiators in §3 (stub-check detection, real health execution, severity rollup, alerting); without them the paid tier is hard to defend since most surfaced checks are config-presence assertions.

Cross-sell. Hard deps already pull capell-app/admin, capell-app/core, capell-app/html-cache and support croustibat/filament-jobs-monitor — natural anchor for the operations bundle. Cross-sell with deployments (Extension Suites / deploy health → “diagnose before/after deploy”), dashboard-reports (shares the health-widget surface and has its own DashboardReportsHealthCheck), and any package with a real health check. Position Diagnostics as the bundle’s “control tower.”

Differentiators / value props / target buyer. Differentiator: cross-package health aggregation + honest stub detection (nobody else can see across the whole install). Value: less SSH, faster incident triage, deploy confidence. Target buyer: agencies/teams running multi-package Capell sites who own uptime.

Keywords/tags (8–12): capell, cms, laravel, filament, diagnostics, system-health, health-check, queue-monitor, config-drift, permission-audit, command-palette, observability. (Current composer keywords are only the first four.)

ItemBucketEffortImpactSection ref
Reflect declared healthChecks classes; report implemented-vs-stub instead of count()DoneMHigh§2, §3, §4 — Done 2026-06-05: BuildPackagesInstalledAction reflects declared classes and the packages widget reports implemented/declared plus stub/broken counts.
Stub/broken health-check detector across all packages (the differentiator)DoneMHigh§3 — Done 2026-06-05: package-installed dashboard surfaces suite-wide declared/implemented/stub/broken totals.
Replace palette danger denylist heuristic with explicit allowlist/risk mapDoneMHigh§2, §4 — Done 2026-06-04: explicit map plus safe/confirm/dangerous tests.
Make DiagnosticsHealthCheck a real check (reference implementation)DoneMHigh§2, §4 — Done 2026-06-05: package catalog, manifest metadata, system-health widgets, and queue-health assertions are translated and key-addressable.
[Shipped] Redact secrets before persisting command_palette_runs.outputDoneSHigh§4
Add RunExtensionHealthChecksAction + capell:diagnostics:health console command (fulfil console surface)DoneMHigh§3, §4 — Done 2026-06-06: executable health report action plus table/JSON/CSV doctor command are wired in the manifest; Done 2026-06-08: --strict fails CI on stub declarations.
Done/Shipped: Single severity rollup / system health scoreDoneMHigh§3 — Done 2026-06-06: extension health reports expose overallStatus, healthScore, and worstSeverity; table, JSON, and CSV output include the rollup.
Wire 6 product screenshots into marketplace.screenshots; rewrite summary + composer description + keywordsDoneSHigh§5 — Done 2026-06-06: six product PNGs plus card are promoted and copy/keywords are outcome-led.
Shipped 2026-06-06: Cache or snapshot expensive scans (config-drift, ownership, public-output) to respect adminQueryBudget=40DoneMMed§4
Shipped 2026-06-07: Persist health-check results to a history table; show trendsDoneMMed§3
Alerting (mail/Slack/webhook) on critical check failureLaterMMed§3
Env/system info panel + runtime liveness (writable disk, cache ping, worker heartbeat)LaterMMed§3
Done/Shipped: JSON/CSV export of health snapshot for support/external monitoringDoneSMed§3 — Done 2026-06-06: JSON output remains on capell:diagnostics:health --json; --csv now emits a summary row plus per-check rows via ExportExtensionHealthReportCsvAction.
Derive package metadata from capell.json; drop hardcoded KNOWN_PACKAGES constLaterMLow§2
Tests: stub-detector, untagged-destructive-command classification, output redactionDoneMMed§4 — Done: fixture coverage exists for suite-wide stub/broken detection, explicit palette risk mapping, and command-output redaction.