Skip to content

Repository files navigation

🚢 Shipwreck Supply Co.
A store that sank on purpose, so the gribbles have something to chew on.

Shipwreck is the deliberately broken example website for Gribble, the AI website audit agent. It is three things at once:

  • An integration test. Every page carries known defects, catalogued in HOLES.md. pnpm eval runs a gate audit and scores what Gribble found against that list.
  • An evaluation set. Change a prompt, swap a model, tweak a rule: run it here and read the recall and the false positives before you believe the change.
  • A demo. It is a small, real-looking SvelteKit store with a catalog, product pages, a cart, a checkout that never quite checks out, a ship's log and a contact form. Broken in about sixty documented ways.

The metaphor is doing a lot of work here. A gribble is a tiny marine isopod that bores into ship hulls from places nobody looks. A shipwreck is what you get when nobody looked. We built the wreck so that we could count the holes.

Run it

pnpm install
pnpm exec playwright install --with-deps chromium   # the browser Gribble drives
pnpm dev                                             # the store on http://localhost:5173
pnpm build && pnpm preview                           # the production build on http://localhost:4173

The site is fully prerendered by @sveltejs/adapter-static. The cart lives in localStorage; there is no backend, which is why the checkout is a dead end and the stock endpoint answers 404. Both of those are on the list.

Audit it

pnpm audit:gate      # deterministic checks, no model needed, about two minutes
pnpm audit:review    # the AI reviewer walks .gribble/flows/*.md (needs model credentials)
pnpm eval            # build, gate audit, then score the report against HOLES.md

gribble.yaml starts pnpm preview for you and points Gribble at the production build. Review mode uses pi's stored credentials (reusePiAuth: true); run pnpm exec gribble login if you have none.

Read the score

pnpm eval (or pnpm eval:report for an existing .gribble/runs/latest.json) prints recall per category, the holes that were missed, and every finding that matches no planted hole. Those last ones are the interesting part: either the site has a hole we did not know about, or Gribble is seeing things. Both get written up.

Recall per category
  a11y       8/8   100.0%
  links      5/5   100.0%
  ...
Gate recall:   50/52 (96.2%)
Missed holes (2)
  P3   perf/image-format   /    The hero is a JPEG that would be a fraction of the size as WebP or AVIF.

The exit code is 1 when gate recall drops below the threshold (--min-recall, default 0.9), so the Evaluate workflow fails when a Gribble change starts missing holes it used to find.

What is planted

Roughly sixty holes across every rule family Gribble implements: broken and empty links, failed requests, console errors, a 2.6 MB hero, layout shift, missing and duplicate titles, two h1s, skipped headings, an accidental noindex, a page with no lang, unlabeled fields, nameless buttons, low contrast, small touch targets, overlapping buttons, horizontal overflow, lorem ipsum and TODOs, leaked translation keys, a Stripe secret in an inline script, duplicate ids, a layout that forgot the viewport meta, a checkout flow that fails at the last step, and copy that breaks the store's own guidelines. Plus a handful of things that look wrong and are not, to keep the false-positive count honest.

The catalogue is HOLES.md. It is dry on purpose. The jokes live here and on the site; the ground truth does not get to be funny.

Layout

src/routes/(shop)/      the store, with header, footer and viewport meta
src/routes/(bare)/      a "focused" layout that forgot the viewport meta and the navigation
src/lib/                products, posts, the cart store, the language map
static/                 images, robots.txt, a sitemap that misses a few routes
.gribble/               gribble.yaml, rules.yaml, guidelines.md, flows/ and the committed baseline
scripts/evaluate.mjs    the scorer
HOLES.md                the ground truth
EVAL-NOTES.md           run history and Gribble bugs found while building this

Adding a hole

  1. Plant it in the site. Keep the rest of the page clean; one hole per element.
  2. Add a row to HOLES.md with the rule, the route, a match string and whether gate or review is expected to catch it.
  3. Run pnpm eval. If Gribble misses it and the rule is implemented, that is a Gribble bug: write it up in EVAL-NOTES.md rather than bending the site until it passes.

License

MIT. Salvage freely.

About

🚢 A store that sank on purpose: Gribble's deliberately broken example site, integration test and evaluation set.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages