OpenParable
Skip to content
← Back to skills

eat-the-broccoli

Testing & Quality

Use when the user says '/eat-the-broccoli', 'eat the broccoli', 'full quality sweep', 'pre-release audit', 'run the deep tests', or asks to hunt for gaps / membrane misses / stubs / dead code / silent failures / the bugs that pass tests but are still broken. A tiered quality-and-pattern audit: deterministic tooling (lint, types, tests, deps, dead-code, silent-failure) PLUS a learned-pattern hunt for the hard, judgment-requiring failure classes that tools can't catch. Works in any repo or stack. Levels: quick / standard / deep. Scope: changed / module / repo.

View on GitHub β†—
QUICK START

How to use this skill

Bring this guide into your coding agent with a prompt tailored to the tool you use.

  1. Open your project in Codex.
  2. Copy and paste the prompt below.
  3. Review files and risks before approving any action.
Prompt to paste
Inspect the Agent Skill at https://github.com/EmpiricaAI/empirica/blob/HEAD/empirica/plugins/claude-code-integration/skills/eat-the-broccoli/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/eat-the-broccoli, but wait for my approval before writing files or running scripts.

Copying this prompt does not install or run the skill. Review third-party files before use.

Eat the Broccoli πŸ₯¦

The thorough quality sweep you run before a release, after a refactor, or when something just smells off. Two halves:

  1. Deterministic tooling β€” lint, types, tests, dependency CVEs, dead code, silent failures. Catches the known categories.
  2. The pattern hunt β€” a checklist of the hard failure classes that pass every test and still ship broken: races, stale caches, silent fallbacks, null-masking, deploy-staleness. Tools can't catch these; only a trained eye plus a "is this by design?" check can.

Portable by design. The deterministic half is tool-agnostic β€” wire in your stack's linter / typechecker / scanner. The pattern hunt needs no tooling at all; it's a structured way of looking.


Two dials: depth Γ— scope

Depthdigs intoScopecovers
quicklint + fast tests + dep-auditchangedthe diff vs your base branch
standard+ dead-code, silent-failure, contract guards, pattern huntmoduleone subsystem / path
deep+ full pattern hunt, docs/contract accuracy, multi-passrepoeverything

Pick any combination β€” quick Γ— changed is a pre-commit reflex; deep Γ— repo is a pre-release gate. State the level + scope you chose, and say what you skipped β€” silent truncation reads as "covered everything."

Forks & monorepos: when most of the tree is upstream/vendored, repo scope drowns in code you don't own. Default to changed or your owned packages β€” here the scope dial is load-bearing, not optional.


Phase 1 β€” Deterministic tooling

Run your stack's equivalent of each. Skip what you don't have; the sweep still works.

DimensionTools
Lint / styleruff, eslint, golangci-lint, clippy
Typespyright, tsc, mypy, cargo check
Testspytest, jest, go test, cargo test
Dependency CVEspip-audit, npm audit, cargo-audit
Dead codevulture, ts-prune, cargo-machete
Silent failuresbare except: / empty catch {} / discarded Result
Contract guardsyour CLI / API contract tests

Tooling by language

The dimensions map to concrete tools. Two reference stacks:

Python

DimensionToolInstall / run
Lint + silent-failureruffpip install ruff β†’ ruff check (silent: --select S110,S112,BLE001)
Typespyrightpip install pyright β†’ pyright
Testspytestpip install pytest β†’ pytest -q
Dep CVEspip-auditpip install pip-audit β†’ pip-audit
Dead codevulturepip install vulture β†’ vulture src/ --min-confidence 80
Complexityradonpip install radon β†’ radon cc src/ --min C
SASTsemgreppip install semgrep β†’ semgrep --config auto
Secretstrufflehogtrufflehog git file://.

Rust

DimensionToolInstall / run
Lintclippyrustup component add clippy β†’ cargo clippy -- -D warnings
Formatrustfmtcargo fmt --check
Types / buildrustccargo check
TestscargoΒ test / nextestcargo test (or cargo install cargo-nextest β†’ cargo nextest run)
Dep CVEs + licensescargo-audit, cargo-denycargo install cargo-audit cargo-deny β†’ cargo audit, cargo deny check
Unused deps / dead codecargo-machete, rustc dead_codecargo install cargo-machete β†’ cargo machete (dead_code lint is on by default)
Silent failuresclippy-W clippy::unwrap_used -W clippy::let_underscore_must_use + hunt discarded Results: let _ = fallible(), .ok(), .unwrap_or_default()
Unsafe auditcargo-geigercargo install cargo-geiger β†’ cargo geiger

The pattern hunt below is language-agnostic β€” it ports verbatim across any stack.

Reading silent failures: a truly-silent swallow (except: pass, empty catch {}, let _ = fallible()) is the dangerous one. A broad catch that logs or re-raises is often deliberate degradation β€” flag the new ones, and any with no log and no re-raise, not the absolute count.


Phase 2 β€” The pattern hunt πŸ₯¦ (the part that earns the name)

Tools find known categories. These are the structural failures that pass tests and still ship broken. Each is a place where broken and by-design look identical β€” so each row carries the disambiguator that tells them apart.

The one meta-question: "This looks intentional β€” is it actually?" When you find a smell, check the intent (a comment, a test, a doc, or ask). When it resolves to "yes, by design," record that verdict (an inline annotation or a .broccoli-accept line β€” see below) so you don't re-litigate it next sweep.

Worked example. You spot a function returning [] on a DB timeout (fallback-masks-primary). Check the intent: does it log or raise? It logs nothing β†’ ❌ broken β€” callers can't tell "no rows" from "DB down." If instead it logged a warning and returned [] as a documented degraded mode β†’ βœ… by design: record it with the reason, move on.

A. State & timing

Smellβœ… by design if❌ broken if
Race / shared mutable state β€” >1 writer to one key/filesingle-writer guaranteed, or the key carries the writer's durable idtwo writers share a proxy key β†’ last-write-wins clobber
Stale cache β€” value resolved once, reusedthe value is immutable for that lifetimeit's ephemeral/locational but frozen at init (location, clock, "current X")
Idempotency miss β€” a retried / redelivered opdedup-key / set-semantics make replay harmlessit increments / appends / re-sends on replay
Off-by-one window β€” a since/until, threshold, rangeinclusive/exclusive matches intentthe event you need lands exactly on the excluded edge
Coupled-lifecycle orphan β€” two things that must live/die togetherbound, or a reaper cleans orphansorphans pile up silently (a handle without its resource; a record opened, never closed)

B. Failure visibility

Smellβœ… by design if❌ broken if
Empty/null masking β€” a field empty because something broke upstreamthe empty has a contract (declared nullable)a count no longer matches its list; a .get(k, default) ate a missing key
Default masks dropped intent β€” a param with a defaultthe default is a real sensible valueit silently absorbs a value that was supplied but got dropped
Fallback masks primary failure β€” a degraded pathit logs/flags that it engaged"it works" actually means "fallback works, primary silently dead"
Partial success as success β€” a multi-step op, one rollup statusrollup is AND-of-all + per-item surfaceda mid-step failure is swallowed by the final OK
Unfalsifiable success β€” no distinct signal for worked-vs-failedsuccess and failure produce different legible outputboth look the same (empty output, silence). Ask: if this failed, could I tell?

C. Boundaries & contracts

Smellβœ… by design if❌ broken if
Classifier blind spot / membrane miss β€” a matcher on crossing datait sees through wrappers / chains / quotes / encodingsa wrapped or chained variant slips a start-anchored match
Encoding / quoting mangle β€” data crossing CLI↔shell, JSON↔DB, wire↔localthe boundary escapes / validates explicitlyit assumes clean input (quotes, newlines, unicode, "0.7" vs 0.7)
Schema drift β€” code assumes a shape the migration didn't producethe unused shape is intentionally deprecated-but-keptthe code path is silently dead against the real schema
Trust-the-input β€” consuming upstream data unvalidatedvalidated at the boundaryit assumes well-formed and NoneTypes three calls later
Two-sources-of-truth drift β€” a copy of a load-bearing thingone is generated from the otherboth are hand-maintained and have diverged
Semantic drift β€” one word, different meanings across componentsone canonical definition, referencedeach component quietly means its own thing (id, session, scope, "done")
Decision downgraded across a boundary β€” a deny/soft decision crossing into a consumer with a narrower vocabularyit degrades to the floor (deny / fail-closed)it silently downgrades to allow β€” the three below
↳ exit-code / status mismatch β€” a host maps a subprocess code to a decision, defaulting on any unrecognized valuethe default is the safe one (fail-closed)unsafe default β€” a crashed gate fails open (e.g. "anything β‰  2 β‡’ allow")
↳ reason-less deny dropped β€” a consumer drops a deny when a required field (reason/message) is empty(never by design)an empty-reason deny silently becomes allow
↳ advisory unsupported downstream β€” an upstream soft decision (ask/warn) the consumer can't expressit degrades to the floor (deny)it silently downgrades to allow (no middle β‡’ must fail safe)

D. Environment & control flow

Smellβœ… by design if❌ broken if
Deploy-staleness β€” installed/copied artifact vs sourcehash/mtime match, or a single source of truththe box runs old code while source is "fixed" (the #1 recurring root cause)
Config/env divergence β€” behavior depends on env / version / run-contextthe dependency is declared + checked with a clear errorassumed present (works interactively, absent in CI / cron / a peer's box)
Authority on the wrong field β€” a gate / filter / recipient checkkeyed on the source of truthkeyed on a proxy that usually agrees
Gate gates its own escape β€” a guard blocking its own clear-paththe recovery action is always-open before the gatethe verb that would clear the deny is itself denied
Unrecoverable gate β€” a deny with a "do X first" messagedoing X actually satisfies itthe satisfaction window closed before X can run
Dead branch by construction β€” a path an earlier check already decidedintentional belt-and-suspendersgenuinely unreachable (shadowed by a prior return)

This table is living. When a new class of issue bites you, add a row with its disambiguator β€” every incident becomes a permanent future check. Found one we're missing? PR it (see Contributing).


Phase 3 β€” Triage, verdict, record

  1. Real issue β†’ log it (an issue, a TODO, your tracker).
  2. Confirmed by-design β†’ record the verdict (an inline annotation or a .broccoli-accept line) so the next sweep skips it.
  3. Roll up a verdict: 🟒 GREEN (ship) Β· 🟑 YELLOW (ship + logged follow-ups) Β· πŸ”΄ RED (blockers β€” name them).
  4. Re-runs are idempotent: track counts over time. A rising silent-failure / debt count is the signal, not the absolute number.

The .broccoli-accept file

One confirmed by-design finding per line β€” a .gitignore for false alarms, so the next sweep stays quiet on what you've already judged:

# pattern:location β€” why it's intentional (and what would reverse it)
fallback-masks-primary:db/cache.py:fetch β€” logged degraded mode; reverse if callers start trusting []
blind-except:sync/git_notes.py β€” non-fatal best-effort write; errors visible upstream

Keep the why. A verdict without a reason is just a mute button β€” and the next person (or the next you) can't tell a real judgment from a silenced alarm.


Contributing

The pattern hunt is meant to grow across languages and harnesses β€” that's the whole point. Hit a failure class that isn't here? Open a PR with a row:

| **Name** β€” the smell | βœ… by design if … | ❌ broken if … |

Real war stories make the best rows. The catalog gets sharper every time someone adds the bug that just bit them.


Why "broccoli"?

Because it's the work you know you should do and skip anyway. This makes it a single command, gives the boring-but-load-bearing checks a place to live, and β€” once a verdict is recorded β€” means you never chew the same stalk twice. πŸ₯¦


Want the deterministic checks bundled into one command, and by-design verdicts recorded for you so they compound across a team? See INTEGRATIONS.md.