A prescriptive, evidence-graded code-quality audit framework for Laravel — run by an LLM, backed by real tools.
cquality is the rubric, not the linter. You point an LLM agent (e.g. Claude Code) at a Laravel codebase; it follows this framework to produce a rigorous, evidence-backed quality audit — 15 dimensions, a 1–5 maturity level each, every metric traceable to a real tool, every judgment call labeled as one.
The repo is the machine. A run produces the report. Nothing here analyzes itself.
Two common ways to assess code quality both fall short:
- "Ask an LLM to review the code." It hallucinates complexity numbers, coverage %, and CVE counts — confident, authoritative, and wrong.
- "Just run the linters." You get raw tool output with no prioritization, no architectural judgment, and no sense of what actually matters.
cquality bridges the two without letting either lie. Deterministic tools produce every number; the LLM orchestrates them, applies prescriptive Laravel standards, judges the genuinely subjective layer — and never launders an opinion into a fact.
The thesis: Laravel is opinionated, and that's leverage. For most problems there is a clean "Laravel way." Most quality problems are deviations from it — and deviations are largely measurable.
- The LLM computes nothing. Every metric comes from a tool (PHPStan, PHPMD, Pest, jscpd, ESLint…). Raw output lives in the evidence appendix. No hand-counted complexity, no estimated coverage.
- Three evidence tiers, never blurred. Tier 1 deterministic · Tier 2 heuristic · Tier 3 judgment. "Cyclomatic complexity is 23" and "this should be an Action class" are never reported with the same authority.
- 15 dimensions, 1–5 maturity each — no vanity score. It refuses the single "health number" on purpose; you read the shape of the vector and the headline risks.
- Prescriptive within a declared stack. A profile declares your stack (Laravel 13, Inertia + React, Filament…); within it there is one blessed way and deviation is a finding. It will not tell you Livewire beats Inertia.
- Read-only. Propose, never merge. The auditor clones, analyzes, and reports. It never edits, formats, or "quick-fixes" your code.
- Multi-language aware. On a Laravel + Inertia + React stack it sweeps both trees — PHPStan/Pint/Pest over
app/, tsc/ESLint/Prettier/Vitest overresources/js. - Markdown-native, zero-install tooling. The framework is markdown; the helper scripts are Python 3 stdlib only — no pip, no
jq.
| Pillar | Dimensions |
|---|---|
| I · Code Health | ① Organization · ② Complexity & Size · ③ Duplication · ④ Type Safety · ⑤ Code Style |
| II · Design & Data | ⑥ Architecture & Layering · ⑦ Design Patterns & Idioms · ⑧ Database & Modeling · ⑨ Frontend |
| III · Runtime | ⑩ Performance · ⑪ Security · ⑫ Observability |
| IV · Process | ⑬ Testing · ⑭ Dependencies & Supply Chain · ⑮ Tooling, CI/CD & Docs |
Maintainability is not a graded dimension — it's derived from Pillar I (grading it separately would double-count complexity, size, and duplication).
Four layered artifacts (see templates/):
| Artifact | Audience | Contents |
|---|---|---|
| Scorecard | exec | stack declaration · 15 maturity levels · derived maintainability · headline risks · tier mix |
| Findings register | engineers | every finding: dimension · tier · severity · confidence · location · the standard it violates · the proof |
| Remediation backlog | planning | findings re-sorted by severity × confidence × effort, each with a lightweight fix |
| Evidence appendix | reproducibility | tool versions · exact commands · raw output — every number auditable |
Pillar I — Code Health
① Organization 4 conventional layout; app/Actions home; no dead code
② Complexity & Size 2 PricingEngine::resolve() CC=27; 3 controllers >120 lines
③ Duplication 2 jscpd 7.1% (threshold 3%); validation duplicated store/update
④ Type Safety 3 Larastan L6 clean; target is L8; 22% of methods untyped
⑤ Code Style 4 pint --test clean; not yet failing the build
Derived maintainability: moderate-LOW — a tidy surface over high complexity + duplication.
No single number. The eye lands on the ②/③ trough immediately. (Full worked example in examples/.)
profile (stack + versions + thresholds)
│
▼ recon.py ........ declare stack · inventory · tool availability
▼ Tier 1 .......... run the deterministic tool spine (report mode only)
▼ Tier 2 .......... apply prescriptive rules, per dimension
▼ Tier 3 .......... apply rubrics to the subjective layer (reasoned, confidence-tagged)
▼ normalize ....... finding schema · dedupe + correlate across tools
▼ grade ........... 1–5 maturity per dimension · prioritize P0–P3
▼
scorecard · findings register · remediation backlog · evidence appendix
Full procedure: framework/06-orchestration-runbook.md.
cquality is run by an LLM agent (built with Claude Code in mind) against a target you control. It's documentation + read-only tooling — not a CLI you install into your app.
- Get a read-only copy of the target Laravel app (clone or branch).
- Recon it (Python 3, stdlib only):
→ versions, detected stack, suggested profile, codebase inventory, and which spine tools are present vs. missing.
python3 tools/recon.py /path/to/laravel-app --human
- Pick / confirm a profile in
profiles/— defaultreference-laravel13-php84; the Inertia + React overlay isreference-laravel13-inertia-react. - Scaffold the run and execute the runbook:
Hand the agent
python3 tools/new-run.py <project> # creates .results/<project>/<run-id>/ from templates
framework/06-orchestration-runbook.mdand let it work the 11 steps. - Read the scorecard, act on P0/P1, and request a deep-dive (
framework/08) for any finding worth a full plan. - Re-run later, then
python3 tools/trend.py <project>for the cross-run maturity delta.
cquality orchestrates tools you already know and adds the interpretation layer. Typical spine (see framework/07-tooling-catalog.md and the supplementary framework/10-tool-gallery.md):
| Layer | Tools |
|---|---|
| PHP | Pint · PHPStan / Larastan · PHPMD · jscpd · PHPMetrics · Rector (dry-run) · deptrac · Pest (+ coverage) · Infection · composer audit |
| JS / TS | tsc · ESLint (react-hooks, jsx-a11y) · Prettier · Vitest / Playwright · knip · bundle analysis · npm audit |
| Recon | tools/recon.py · new-run.py · trend.py — Python 3 stdlib, no installs |
Every tool runs in report / dry-run mode only — the target is never modified. Tools that aren't present are logged as skipped, with a reason (no silent gaps).
A profile is the only place version- and stack-specific rules live; the framework/ and dimensions/ core stays generic. Shipped:
reference-laravel13-php84.md— Laravel 13 / PHP 8.4 backend (Blade + Livewire).reference-laravel13-inertia-react.md— overlay for the Laravel → Inertia → React starter kit.
Onboard a new target by copying profiles/_TEMPLATE.md and declaring versions + stack idioms + any threshold overrides.
- The LLM computes nothing. Metrics come from tools. If a number appears, a tool produced it and the raw output is in the appendix.
- Never launder a Tier-3 opinion into a Tier-1 fact. Every finding carries its evidence tier and — for judgment — explicit reasoning and a confidence level.
- The target is read-only. Clone, analyze, report. No edits, no PRs, no "quick fixes."
These are the framework's credibility; violating one produces a report that looks authoritative and is wrong. Full rules: framework/01-principles.md.
framework/ the reusable, version-agnostic IP — principles, evidence tiers, maturity
model, severity model, finding schema, runbooks, tool catalog
dimensions/ the 15 dimension specs — the "what to check"
profiles/ per-stack overlays — the "for THIS app"
templates/ the four output artifacts a run fills in
tools/ read-only Python helpers (recon · new-run · trend)
examples/ a worked, hypothetical run, end to end
CLAUDE.md operating & extension guide — read this to extend the framework
.results/ per-project run history (generated; gitignored)
CLAUDE.md is the extension guide: how to add a dimension, tune a check, add a profile, or add a tool to the spine — and the guardrails you must not break. Check IDs are stable (renaming breaks cross-run delta tracking); version-specific knowledge lives in profiles, never in the core.
- Not a linter or a tool — it orchestrates tools and adds the judgment layer.
- Not a refactoring agent — it proposes, it does not change your code.
- Not stack-zealotry — prescriptive within your declared stack, agnostic about which stack you chose.
- Not a single grade — it refuses the vanity number by design.
The framework is the deliverable: documentation + read-only Python recon/trend tooling. The audit itself is executed by an LLM agent following the runbooks. The reference profile targets Laravel 13 / PHP 8.4 — see the version caveat in CLAUDE.md §9.
Issues and PRs welcome — especially new profiles (other Laravel stacks/versions), additional tool-spine integrations, and dimension refinements. Keep edits within the existing shape (consistency across the docs is the whole point) and read CLAUDE.md first.
MIT © Zach Mowrey