Agent Automation
Two Skills, and the Bugs That Wrote Them
Tonight I shipped one app to both stores and built two skills out of what went wrong on the way.
Canon is a shipping problem now
Suede Voice's vocal domain is implemented four times: a TypeScript reference, a companion web app, a SwiftUI app, an Android app. The constants had been travelling between them by hand, copied out of handoff documents into a second language.
Nothing ever failed. That is the whole problem. A wrong copy does not crash. The two surfaces simply start scoring the same performance differently, and nobody finds out until a singer does.
Writing the contract surfaced three divergences. The iOS app clamped song transpose to two octaves where the web clamped one. Every drill in the shipped app counted in three beats where the web counted four, and no production call site overrode the default. Both had shipped. None of the four surfaces had a test that could notice.
The engineering fix is ordinary: generate a contract from one reference surface's live constants, vendor it to the others, assert against it. What makes it worth a skill is the discipline around the edges. Assert through public behaviour, because a follower that reimplements the reference formula only proves you can write the same bug twice. Check a threshold at its boundary and one step below, because one asserted only from above still passes after it moves down. Pin the divergences you already have rather than erasing them, and guard the pin list itself, or an entry added elsewhere is a silence instead of a failure.
And treat finding a divergence as a stop, not a fix. Which surface is right is a product call. Changing a shipped constant changes behaviour for people who did not ask for it.
There is a second reason this matters that did not exist a few years ago. AI search decides what to quote, and it quotes sources that agree with themselves. Facts scattered across a site, two store listings and a docs page are four chances to contradict yourself in a way a model can read. Canon consistency stopped being tidiness and became a distribution property.
The Console was the slow part
The Android half of the night started with no way to talk to Google Play at all. Releases ended with a signed file handed over by hand.
The skill closes that. Credentials, upload, track promotion, staged rollout, per-locale release notes, and verification all run from the agent interface. You open the Play Console exactly once, to grant the service account release access, because that grant has no API.
Every rule in it is there because something bit:
- A new service account returns 403 until that grant lands, so the skill preflights with a real API call before anything else.
- The macOS security command hex-encodes multi-line secrets on read, so the credential is stored base64 and comes back in one shape instead of two.
- The publishing identity is separate from the billing one, because a credential that can push releases should not also be able to void purchases.
- fastlane reads the working tree, so a stale checkout produced a run that reported success and did nothing.
- A missing changelog is a silent skip, so three languages nearly shipped reading the previous version's notes.
- Play rejects a duplicate versionCode, so you promote the artifact your test track already validated rather than re-uploading.
- A staged rollout at 100 percent and a completed release look the same in a success message, so the last step reads the track back from the API and says which one you got.
That last rule is the shape of both skills. A green summary is a claim. The readback is the evidence.
Getting them
Both ship in the Suede Creator Skills pack, which is public.
/plugin marketplace add JasonColapietro/suede-creator-skills
/plugin install suede-skills@suede
Then ask in plain words. "Ship the android build" or "stop the app and the website disagreeing" routes to the right one. The docs for suede-play-release and suede-parity-contract carry the full rule lists.