Agent-readiness hardening — mobilerun-portal
Context
An external code auditor cold-emailed us with specific findings about droidrun/mobilerun-portal. We independently verified the claims against the repo — all of them check out. The root cause: we wired Claude into the PR flow (.github/workflows/claude.yml, claude-code-review.yml), but the only written agent guidance is a ~4-line code-style.md. No CLAUDE.md / AGENTS.md anywhere. So an AI agent (or a new contributor) can't see the invariants a real reviewer carries in their head.
The recurring shape: non-exhaustive Kotlin when blocks with an else arm that silently swallows newly added enum members, in files with no tests. Every other surface (UI picker, API catalogue) enumerates from .entries automatically, so a new trigger shows up in the UI and API but the one place that decides whether it fires returns null.
Note: none of these are shipped bugs today — all mapping arms are currently correct. This is about shape/risk, especially now that an agent edits this code.
Verified findings
- No
CLAUDE.md/AGENTS.md; only a 4-linecode-style.md. TriggerRuntime.handlePortalEvent— 13 hand-written identity arms +else -> null, disabling exhaustiveness. 971-line file, zero tests.- Two disagreeing
isNotificationSourcefunctions (TriggerEditorSupport= POSTED||REMOVED, public;TriggerRuntime= POSTED only, private). visibilityFor(+capabilitiesFor,defaultCooldownSecondsFor) has a load-bearingelse— a new source silently gets no cooldown/run-limit and is invisible.
Sub-issues
See children. The CLAUDE.md one is the anchor (fixes the root cause); the exhaustiveness fixes remove the actual footguns.
Source: external audit email + our own verification (GitHub, 2026-07). We do not need to buy the $99 audit to fix these four — they're fully specified.
Source: droidrun/mobilerun