- migration 013: cja_qa_runs + cja_qa_findings - runner: runQa (crawl pages/links/images/external/contact-probes/health/ SEO/meta/sitemap/a11y), qaTriage (LLM summary via qa skill), /devconsole/qa/run - qa-start/finish/routes.php CLI bridge - adminqa controller (runs/findings/fix/ignore); fix() chains to the Web Designer queue; /admin/qa report page + nav link - qa skill; contact form probed via honeypot (writes nothing)
68 lines
4.2 KiB
Markdown
68 lines
4.2 KiB
Markdown
---
|
||
name: qa
|
||
description: Quality-assurance testing for the Carlos Arias website (carlosarias.co). Use when summarising a QA run, triaging findings, deciding severity, or fixing an issue the QA agent found (broken link, dead image, form failure, SEO/meta gap, sitemap gap, missing alt text). Explains what the site's QA covers, how severe each kind of issue is, and the gotchas of testing this specific site.
|
||
---
|
||
|
||
# Skill: QA for carlosarias.co
|
||
|
||
The site is a **static Astro build** (content baked from `cja_projects` / `cja_changelog`
|
||
at build time) plus a small **PHP API** at `/api`. The only live runtime endpoints are
|
||
`POST /api/contact/submit` and `GET /api/health`; everything else is pre-rendered HTML. So
|
||
QA is HTTP-based: a crawler fetches pages and parses the served HTML — no browser, no JS
|
||
execution.
|
||
|
||
## What a QA run checks
|
||
|
||
| check_type | What it verifies | Default severity |
|
||
|---|---|---|
|
||
| `page` | Every route returns 200 with HTML | **error** if not 200 |
|
||
| `link` | Every internal `<a href>` resolves (200) | **error** |
|
||
| `image` | Every `<img src>` / og:image / icon loads | **error** |
|
||
| `external` | Off-site links (social, project `links.live`) reachable | **warning** |
|
||
| `form` | `/api/contact/submit` alive (honeypot probe → 200) + rejects bad input (→ 422) | error / warning |
|
||
| `health` | `/api/health` returns 200 and `db:"connected"` | **error** |
|
||
| `seo` | Each page has a `<title>` + meta description; canonical host is carlosarias.co; titles aren't duplicated | warning (error for wrong canonical host) |
|
||
| `sitemap` | Every route appears in `sitemap.xml` | **warning** |
|
||
| `a11y` | Images have `alt`; `<html lang>` is set | **warning** |
|
||
|
||
## Severity model
|
||
|
||
- **error** — the site is broken for a real visitor: a page/link/image 404s, the contact
|
||
form or API is down, or canonical URLs point at the wrong host. Fix promptly.
|
||
- **warning** — degraded but working: a missing meta description, a page absent from the
|
||
sitemap, missing alt text, or an external link that looks dead. Fix when convenient.
|
||
- **info** — notes, no action needed.
|
||
|
||
## Site-specific gotchas (important)
|
||
|
||
- **Contact form is honeypot-probed, never really submitted.** The form has a hidden
|
||
`company` field; if it's filled, the server returns `200 {received}` and writes **nothing**.
|
||
QA fills it on purpose so the "is the endpoint alive" probe leaves no `cja_contact` row and
|
||
sends no email. A separate probe sends a too-short `message` to confirm validation returns
|
||
422. Never treat these probes as real leads.
|
||
- **External links are warnings, not errors.** Sites like Instagram/LinkedIn frequently
|
||
return 403/429 to bots or time out — that is not proof the link is broken. Only a clear
|
||
404/410 or DNS failure is flagged, and only as a warning. Don't over-react.
|
||
- **Known sitemap gap:** `sitemap.xml` currently omits `/projects`, `/changelog`,
|
||
`/services`, `/resume`, `/faq`. These will show as `sitemap` warnings until
|
||
`app/src/pages/sitemap.xml.js` is updated to include them.
|
||
- **Duplicate titles** usually mean a page didn't set its own `<title>` and fell back to the
|
||
site default in `BaseLayout.astro`. The fix is a page-specific title/description prop.
|
||
- **Static build:** a content fix (e.g. a project's broken `links.live`) lives in the DB
|
||
(`cja_projects`) or a page's `.astro`, and only goes live after a rebuild — which the
|
||
console handles. Don't expect a DB edit alone to change the live page.
|
||
|
||
## Fixing a finding
|
||
|
||
Each finding carries a `fix_hint` — a ready-made instruction. When the admin turns a finding
|
||
into a Web Designer fix task, that hint becomes the task prompt. When you (as the Web
|
||
Designer) act on it: make the smallest correct change on the named page, stay on-brand (see
|
||
the `brand` skill), and let the console build/publish. Prefer fixing the source of a bad link
|
||
(the nav/footer/component or the `cja_projects` `links` value) over patching one instance.
|
||
|
||
## Writing the run summary
|
||
|
||
When asked to summarise a run: 2–4 sentences, plain English, for the site owner. Lead with
|
||
overall health ("clean" / "a few warnings" / "N errors need attention"), name the most
|
||
important thing to fix first, and say whether anything is urgent (a down form or API, a 404
|
||
on a linked page). No preamble, no restating every finding.
|