| name | red-team-review |
| description | Launch a skeptical bug-hunting code reviewer (Opus) to find real bugs, correctness issues, and trust hazards in this project's production code and data pipeline — not style nits. Use when the user asks for a "red team", "bug hunt", "break-it review", or at checkpoints after a milestone lands (especially before any publish/deploy). |
Red-team bug hunt (production review)
A skeptical break-it review: launch an Opus general-purpose agent to
hunt for real bugs in the production surface — the Svelte/Vite web app
under web/src/ and the derivative pipeline under scripts/. The method
and hazard categories below are universal; the invoking agent supplies this
project's specifics from AGENTS.md at call time.
Complementary to test-red-team (the suite, once
one exists) and mutation-red-team (dynamic
check); run all three at major change points.
When to invoke
- User says: "red team", "bug hunt", "break-it review", "find what's
broken", "find real bugs"
- A significant batch of new production code just landed
- Before any publish/deploy — this repo ships one person's photos,
coordinates, and dates; a wrong-result-that-looks-right here can leak
personal data. This is the highest-value moment to run it.
- Proactively at checkpoints during long coding tasks
How to invoke
Use the Agent tool with:
subagent_type: "general-purpose"
model: "opus"
description: 3–5 word description (e.g. "Red-team the pipeline")
prompt: fill the bracketed sections below — do NOT send as-is. The
bracketed context is what specializes a generic hunt into a sharp one;
read AGENTS.md and translate each invariant into a concrete thing to break.
Prompt template
You are a skeptical code reviewer performing a break-it bug hunt. You find
real bugs, correctness issues, and trust hazards — NOT style nits. Rank
findings by severity (CRITICAL / HIGH / MEDIUM / LOW).
## Project
The repo root (`git rev-parse --show-toplevel`). Read AGENTS.md first — its
principles and the docstring of scripts/build_derivatives.py define what
counts as broken.
cheap-eats is a personal data visualization: a Svelte 5 + Vite globe
(web/src/) rendering 202 food photos/videos, fed by a committed Python
pipeline (scripts/build_derivatives.py) that turns read-only source media in
data/ into the derivatives + manifest.json that actually ship. The trust
model is: source media is frozen input; ONLY derivatives are published; the
publish gate must verify the derivative that ships, never just the source.
Load-bearing invariants to attack (each is a thing to break):
- The GPS/publish gate (verify_no_gps in build_derivatives.py): NO location
metadata may survive on any derivative the script wrote. A path that
ships a file the gate never checked, or a gate that passes while EXIF/
QuickTime GPS survives, is CRITICAL.
- Publish derivatives, never originals — no code path serves or copies a
data/ source (or a *_original sibling) to the shipped site.
- Media identity is a stable slug: every derivative and manifest entry is
named from one slug by convention; files, manifest, and web/src/lib/data.ts
must never disagree about what a thing is.
- Determinism / reproducibility: rerunning the pipeline on the same inputs
yields the same outputs (incremental `fresh()` staleness, slug-collision
assert, manifest ordering).
## Production surface to review
[Name the files/dirs in scope. Default: web/src/ (App.svelte, lib/Globe.svelte,
lib/data.ts, lib/lightbox.ts) and scripts/build_derivatives.py. If a batch of
changes just landed, list them with file:line anchors; otherwise the full
surface above.]
## What to hunt (universal hazard categories — specialize each to this code)
- Wrong result that looks right: any path that turns a failure into an
apparent success, loses the original error, or reports done before it
was — the most dangerous class because nothing looks wrong. Here: a
publish gate that greenlights media it never inspected.
- Personal-data leakage: a derivative that ships with GPS/EXIF/QuickTime
location metadata intact; a manifest field, thumbnail, or filename that
exposes something the maintainer did not choose to publish.
- Input handling: a locations.csv row, filename, or slug with unexpected
characters/encoding reaching a path join, a shell arg (exiftool/sips/
ffmpeg), a fetch URL, or the DOM without escaping/validation.
- State & correctness: races in the ThreadPoolExecutor build, non-idempotent
or non-incremental steps, reused/colliding slugs, off-by-one in the
clustering/projection math in data.ts and Globe.svelte.
- Resource & cleanup: temp files, canvas/rAF loops, or PhotoSwipe instances
left behind; a partially-written derivative that the gate then passes.
- Determinism & reproducibility: output that depends on wall-clock, dict/map
ordering, or filesystem order where it must not; a "reproducible" step
that isn't.
- Trust boundaries & contracts: the manifest schema (data.ts Item/Cluster)
changed on one side only; an irreversible or outward-facing action
(publish/deploy) reachable without its human checkpoint.
- Assumptions asserted without evidence: behavior the code depends on
(exiftool/sips/ffmpeg flags, d3-geo projection, HEIC handling, browser
APIs) that was never probed.
## Output format
~300–500 words. Group by severity. For each finding:
- file:line reference
- one-sentence description of the bug
- one-sentence trigger condition
Do NOT propose fixes (just the bug). End with a one-sentence risk delta vs
the previous review if one exists.
Be terse. Be specific. Find real bugs.
Scripts and assets
No scripts. Helpers, if ever needed, live in this folder only.
Cleanup discipline
This skill must clean up after itself. The review agent is read-only by
design and should not create files.
- Temporary prompt files → delete after the agent returns.
- Scratch analysis dumps → delete unless the user asked to keep them.
- The agent's response belongs inline in the conversation; do NOT write it
to a
.md file in the repo unless requested.
- Final
git status check before returning control.
Findings accepted rather than fixed go where the knowledge lives (a comment
at the code site, or the relevant doc under docs/) with the reasoning, so the
next agent neither re-"fixes" them nor builds on them unaware.