accessibility-gate
Use as a pass/fail gate on any diff with a user-facing surface — by code-reviewer during review, by qa-engineer during the test pass, and by any IC before…
Use when reviewing code, auditing an app, writing a guard rule or test, or certifying any threshold/constant/formula. Finds the defects a diff review structurally cannot see — the second write path, the mis-calibrated constant, the rule that cannot fail. Triggers from
$ npx -y skills add vmobifystudio/app-dev-team --skill defect-hunting --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/defect-huntingContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when reviewing code, auditing an app, writing a guard rule or test, or certifying any threshold/constant/formula. Finds the defects a diff review structurally cannot see — the second write path, the mis-calibrated constant, the rule that cannot fail. Triggers from
name: defect-hunting description: Use when reviewing code, auditing an app, writing a guard rule or test, or certifying any threshold/constant/formula. Finds the defects a diff review structurally cannot see — the second write path, the mis-calibrated constant, the rule that cannot fail. Triggers from code-reviewer, /app-audit, qa-engineer, verification-engineer, and any task that adds a lint rule, architecture test, or CI grep.
Mined from a real remediation programme where twelve screen-by-screen review rounds found nothing new, and one round organised differently found dozens of live defects. Every one of these rules is paid for.
**The sentence that generates all four:**
> Verify the thing that has to be true, not the thing you changed.
Filtering the list is not filtering the parser. Capping the severity is not capping its renderer. Matching the token is not matching the value. Mutating the file is not confirming the mutation landed.
---
A review organised by screen structurally cannot find these, because in every case **the audited surface was correct and the bug was in the second path to the same data** — usually another file, often another module:
| What was reviewed | Where the defect actually was | |---|---| | Add-form validation | the **edit** path, which validated nothing | | the dashboard alert banner | the **detail screen** the banner opens — they disagreed | | the growth-target reader | the **writer**, which destroyed data | | the photo picker's success branch | its **cancel** branch, which wiped the existing photo | | the purchase flow | the **still-loading** entitlement state, which paywalled a paying customer | | sync's happy path | the `RECONCILE_FAILED` branch |
> **"What is the second way this value gets written?"**
And its siblings: what is the second way it gets *read*? What happens on cancel? On failure? On restore? On import? On sync? On each remaining enum case?
Before approving any change that touches persisted or user-visible state:
1. Name the data the change touches — the field, the row, the preference, the entitlement. 2. **Enumerate every writer.** `grep` the field name across the whole repo, not the module — prefer `ast-grep` where the language has one available, same reasoning as §1b: text search false-negatives on a renamed reference or a match sitting inside a comment or string. Create, edit, import, sync, restore, migration, reset-to-default, and every failure branch. 3. **Enumerate every reader**, same way. 4. Show the invariant holding **on each one**. A validation that one producer applies and another walks around is not a validation. 5. If you cannot enumerate them, say so — do not approve on the strength of the path you read.
A one-line fix at the shared choke point beats a guard in every caller, and it is also the *lazier* fix. Patching only the path the ticket names leaves every sibling caller broken.
---
Found in this studio's own work, by a review that finally checked mechanically instead of by eye: a component (`VerdictBar`) was written, exported, and never imported anywhere. It typechecked. It built. It shipped in a merged PR. Nothing in §1–§4 would have caught it, because §1 asks whether a value's *other* writers and readers agree with each other — this is the narrower, cheaper question of whether the diff's *own* new code is ever reached by anything at all.
> **"Who calls this, outside its own definition?"**
Applied to every function, component, type, constant, or route the diff introduces.
1. For each new symbol the diff adds, search for a real call/reference site **outside the file that defines it** (or outside its own declaration, for a symbol used only within one file). `export`ed with zero importers is the specific, mechanical shape to catch — `grep -rn '<Name>' src/ | grep -v '<file that defines it>'` at minimum; prefer an AST-aware search (`ast-grep`) over plain `grep`/`rg` where the language has one available, since text search false-negatives on a renamed reference or a match sitting inside a comment or string. 2. **Missing co-changes** — the same "enumerate" discipline as §1, aimed at what a change like this one *always* requires alongside it, not at what it says it changed: an implementation with no test file for it, a new database column with no migration, a new API handler with no route registration, a changed struct/type with no update to its (de)serialization. Name the class of companion this diff's *kind* of change requires, then confirm each one is actually present. 3. Dead code found this way is not a style nit — it is unreviewed, untested surface area sitting in the codebase looking finished. Either wire it in or delete it. "Leave it for later" is how it becomes permanent.
---
An age-aware plausibility envelope read perfectly sensibly, survived 35 sprints and every review. Executed against the app's own bundled reference table, it rejected the **median** child at 26 of 61 ages: an average 12-month-old was told their measurement looked wrong.
Mis-calibration is invisible to inspection **because the code is correct**. The arithmetic does exactly what it says. Only the numbers are wrong, and numbers do not read as wrong.
Same failure shape as a fabricated reference standard and a wrong lookup table forced on the wrong population: plausible-looking numbers that nobody ever ran.
Any threshold, bound, formula, coefficient, table, or rate that makes a **clinical, financial, or safety claim** must be checked by *executing it across its whole input range against reference data*, and the comparison recorded.
for every input across the re
Describe your app idea in one line. Get a shipped iOS & Android app. AI App Studio is a team of 30 AI specialists — a CEO, product manager, designers, iOS/Android engineers, a code reviewer, QA, and a release manager — that works like a real software studio.
Repo: vmobifystudio/app-dev-team
Use as a pass/fail gate on any diff with a user-facing surface — by code-reviewer during review, by qa-engineer during the test pass, and by any IC before…
Use before spawning any agent that writes files, and by every developer/fixer agent as its first and last action. Gives each agent its own git worktree,…
Use to produce the technical architecture doc and engineering principles for a mobile app. Used primarily by the CTO agent. Triggers on "design the…
Use to validate docs/31-board.md before spawning any agent, and to verify a developer's "DONE" claim before moving a row to review. Triggers as step 0 of…
Use when pointing the team at an EXISTING, already-built app instead of a blank project — detects the stack, reverse-engineers the as-built architecture, and…
Use when deciding or revisiting how the product makes money — pricing, tiers, trial shape, ad load, unit economics — by ceo when setting the model, by cpo when…