Track: The Taskmaster. Bonus models — all three: Gemma 4 (in the release path as the rejection classifier), Veo 3.1 (demo intro), Lyria (demo score). The narration is Google Cloud Text-to-Speech: every visual and every sound in this submission was produced by the Google stack it demonstrates.
Inspiration
I have 14 apps on the App Store. The week before this hackathon I spent two days taking a new one from "build uploaded" to "Waiting for Review" by hand: bundle id, app record, subscription group, localizations, 175 territory prices, availability, review screenshots, metadata. I hit a 55-character limit I'd forgotten, a rerun that silently skipped a localization, and an availability default that would have left an in-app purchase buyable in exactly one country. I keep a 64-row error index of these. That index is the product.
What it does
A build appearing in App Store Connect wakes the agent (Apple webhook → Cloud Run). Seven agents then take the version to Waiting for Review unattended: an intake agent, a metadata writer and a separate critic in an ADK LoopAgent, a screenshot compositor that never lets an image model redraw the UI, a parallel compliance preflight that encodes the error index as API checks with auto-fixes, a triple-gated submission agent, and a webhook-driven watcher that routes Apple's rejection text back to the right agent via Gemma 4 + Gemini.
On its first real run against a fresh app record it found 13 blocking problems, auto-fixed 13, surfaced 4 one-click web-only gates, and — via Gemini vision over the real captures — flagged a paywall promising features the build doesn't have and a cleartext password in the sample data. Those two are rejections; no API field could have revealed them. The submission in the demo video is real: SnipStash 1.0 is sitting in Apple's review queue right now, submitted by the agent.
How we built it
Google ADK 2.7 (Agent / LoopAgent / ParallelAgent / custom BaseAgent checks) · Gemini 3.5 Flash on Vertex AI · Gemma 4 via the Gemini API · Cloud Run (scale-to-zero, one image, three roles) · Pub/Sub push with OIDC and a dead-letter topic · Firestore for multi-day job state · Cloud Storage · Secret Manager for the ASC .p8 (read at runtime, never an env var, never in the image) · Cloud Scheduler reconcile · raw App Store Connect REST with ES256 JWTs, backoff, and a read-back after every write.
Challenges we ran into
buildUploadsis GET-instance only and carries no build relationship — the build turned out to share the upload's UUID. A crash on the very first real delivery was absorbed by Apple's retry/redeliver.- Live on submission night, Apple threw an undocumented 409: a brand-new subscription group cannot be submitted unless the subscription inside it is staged for review too. The agent surfaced the exact error into the job record; after one staged click it re-queued itself and the submission went through. It's in the demo video, unedited.
- Several submission gates are web-only by design (App Privacy publish, medical-device banner, Paid Apps Agreement, first-IAP draft attach). The honest answer is to surface them as operator items, not hide them.
- The Gemini API free tier has zero quota for Veo/Lyria — those run on Vertex instead.
Accomplishments that we're proud of
Real push trigger from Apple, verified HMAC, first delivery to a job in under 2 minutes of upload. A critique loop that converges in one round because the critic has a deterministic validator as a tool. A preflight whose every row is a rejection I already paid for. And a real app, really submitted, by the agent.
What we learned
A 2xx from Apple means stored, not done. Give the critic tools, not taste. Vision on real pixels catches what fields can't. Surface the gates you can't automate instead of pretending.
What's next for Shipwright
Gmail watcher for Resolution Center text so rejections route with zero paste; multi-locale metadata; TestFlight beta-review path; Google Play support (same pipeline, different API layer); running it across all 14 of my apps.
Try it without an Apple account
scripts/demo_replay.py runs the full agent tree against recorded responses from the real release — bring a free Gemini API key. Details in the README.
Disclosures: built new during the submission window. Pre-existing assets: my personal error-index playbook (data, not code) and the demo target app SnipStash. Solo build, AI-assisted development.
Log in or sign up for Devpost to join the conversation.