console: agent-first mode (console plan / console verify), verified App Privacy and Play Create app facts

- `storebound console plan <form> [--json] [--lookup]`: read-only plan for an AI agent that drives the browser
  itself: start URL (deep links), ordered steps, answer sheet with the console's exact labels (certain / ask owner,
  curly quotes noted), never-press list, verified UI facts, driving guidance (in-page async loop + window.__log),
  verify instructions. All six forms.
- `storebound console verify <form> [--from-text <file|->]`: App Privacy per-type summaries from page text, Play
  Create app from input states, content rating / target audience summaries, App Store record and age rating from
  the API; exit 1 on a mismatch.
- MCP: console_plan, console_verify (read-only); console fill stays off MCP.
- App Privacy (verified 2026-10-12): two information steps, unlabeled purpose checkboxes (nearest parent text),
  "Definitions and Examples" never pressed; fixture and engine follow.
- Play Create app (verified 2026-10-12): /developers/<id>/create-new-app, App package name + read-only Check
  availability, material-radio inner [role=radio] click, app dashboard URL and play.appId, service account
  "Add app" as an owner step.
- console-autofill skill rewritten agent-first; agents-core rule 10; README; pitfalls 12, 18 (confirmed sign-out),
  19; CHANGELOG; play-first-release.
This commit is contained in:
CRTkafa 2026-10-12 08:22:03 +08:00
parent a9261a8052
commit c9a7f095c4
34 changed files with 1430 additions and 113 deletions

View file

@ -1,21 +1,82 @@
---
name: console-autofill
description: AI-assisted autofill of App Store Connect and Google Play Console forms that have no API (the New App dialog, App Privacy, Play's Create app form, the Play IARC content rating questionnaire, Target audience and content plus the Ads declaration; the App Store age rating is shown as guidance because the API sets it) in a visible browser with storebound's own profile that the owner signs in to once (never a copy of the owner's Google cookies unless they opt in); storebound opens the form itself. Answers come only from storebound.config.ts; anything the config does not prove stays empty and highlighted. storebound moves through the pages itself (Next; App Privacy: Get Started, Edit, each data type and the draft Save; content rating: Save draft) and never signs in, submits or publishes: the owner presses the final button. Use when the user wants help filling one of these console forms, asks what to answer in them, or wants the answers as a checklist.
description: Fill App Store Connect and Google Play Console forms that have no API (New App, App Privacy, Play Create app, the IARC content rating, Target audience and content plus Ads; the App Store age rating is guidance because the API sets it). Agent-first by default - `storebound console plan <form> --json` (MCP console_plan) gives the start URL, steps, answer sheet with the console's exact labels, never-press list and verified UI facts; you drive the page with your own browser tool (Claude in Chrome, a built-in browser, Playwright), stop before the final button and tell the owner what to press, then `storebound console verify <form>` (MCP console_verify). `storebound console fill` is the optional scripted fast path. Answers come only from storebound.config.ts. Never sign in, submit, publish, accept agreements or grant permissions. Use when the user wants help filling one of these console forms, asks what to answer in them, or wants the answers as a checklist.
---
# Console autofill (forms without an API)
# Console forms without an API
CLI: `storebound` (or `bunx storebound` in a project that has it, or `bun <toolchain>/cli/index.ts`).
**Read this to the owner first.** Console pages change without notice. This is AI-assisted autofill and it may put an
answer in the wrong place. The owner reviews every field and presses the final button. storebound never types a
password, never touches a sign-in page, never prints or sends a cookie, and never clicks Submit, Publish, Create, a
final Save or anything that sends a form for review (English or Turkish console). It clicks only what moves through
the form (see "What storebound clicks" below). It works in its own
browser profile where the owner signs in once by hand. It never copies the owner's Google cookies unless the owner
opts in (`--use-chrome-session google`), because Google binds them to the device and may sign the owner out of their
real Chrome (step 3).
It is not available over MCP.
**Read this to the owner first.** Console pages change without notice. You (the agent) fill the form from storebound's
answer sheet and the owner reviews every field and presses the final button. Nobody types a password or touches a
sign-in page except the owner; nothing that submits, publishes, creates, accepts an agreement or grants a permission
is pressed by you or by storebound.
## Default: agent-first (you drive the browser)
storebound supplies the knowledge and the check; you drive the page with your own browser tool and adapt to whatever
the UI shows. This is the primary mode.
1. `storebound console plan <form> --json` (MCP: `console_plan`; read-only, offline; `--lookup` asks the App Store
Connect API for the app id). It returns:
- `start`: the URL (a deep link when `apple.appId`, `play.developerId` or `play.appId` is known, or the ids
storebound remembered) and how to reach the form otherwise;
- `steps`: plain language plus what to `click` (by visible text) and which `answers` go on each step;
- `answers`: every answer with `status` (`certain`, `ask-owner`, `owner-check`, `agreement`), the console's own
`label` (curly quotes as shown, `curlyQuotes: true`), `action` (tick / untick / pick / type / choose) and `where`;
- `buttons.neverPress` (Publish, Submit, Create, Create app, Send, Release, "Definitions and Examples", "?", the
final Save of a form ...), `buttons.final` and `buttons.allowed` (navigation and draft saves);
- `uiFacts` (verified facts per form, see below), `driving` and `verify` (the command and what to capture).
2. Show the owner the `ask-owner` answers and ask (AGENTS.md rule 5). Never guess them; leave them empty if the owner
wants to answer in the page.
3. Open `start.url` in your browser tool. If a sign-in page shows, the owner signs in; you wait.
4. Follow `steps`. Read the page (text or accessibility tree) before each action, click by visible text, set each
answer as the sheet says, wait for the next step to render. If the page differs from the plan, adapt (the console
changes), but never press anything in `buttons.neverPress` and never tick an agreement.
5. Long flows (App Privacy with many data types): one evaluate call times out around 45 s, so start an in-page async
loop and poll it:
```js
window.__log = []; window.__run = (async () => { /* for each step: wait for it, act, */ window.__log.push('Device ID: purposes set'); /* ... */ window.__log.push('done'); })().catch(e => window.__log.push('stopped: ' + e.message));
```
then read `window.__log` every few seconds until it says `done` or `stopped`. Never click past a step you have not
read; on an unknown step, stop the loop and look.
6. Stop before `buttons.final` and tell the owner exactly what to press (App Privacy: review the summary, press
Publish; Play Create app: tick the two declarations, press Create app; content rating: Submit; target audience:
Save; New App: Create).
7. `storebound console verify <form> --from-text -` (MCP: `console_verify` with `text`) with what `verify.capture`
says: App Privacy the page's `innerText`, Play Create app the JSON of the capture snippet. Exit 1 / mismatches:
fix them in the page (or the config), verify again. `apple-app-record` and `apple-age-rating` verify from the API
without text.
### Verified UI facts
- **App Privacy** (`/apps/<id>/distribution/privacy`, 2026-10-12): "Set Up <type>" is a plain `<p>` with a click
handler (click it by exact text); it opens a `<dialog>` whose h2 is the type. Step 1: 6 purpose checkboxes in the
order Third-Party Advertising, Developer’s Advertising or Marketing (curly ’), Analytics, Product Personalization,
App Functionality, Other Purposes; an input has no aria label, its label is the nearest non-empty parent text
(label and help text run together). Step 2: radios "Yes, <type> data collected from this app is linked to the
user’s identity" / "No, …". Steps 3 and 4: two information pages ("Let’s define two important terms…", "To help put
tracking into context, here are a few examples:"), no inputs: Next on each. Step 5: radios "Yes, we use <type> data
for tracking purposes" / "No, …", plus "Definitions and Examples" (never press), Back, Cancel, Save. Save closes the
dialog; the type then shows Edit and a summary ("Used for …", linked, tracking), which `console verify` reads.
- **Play Create app** (2026-10-12, through Claude in Chrome): `/console/u/0/developers/<developerId>/create-new-app`.
App name (max 30), App package name (max 150) with a read-only "Check availability" ("Package name available";
press it), Default language (default "English (United States) – en-US"), App or game and Free or paid as
`<material-radio>`s, two declarations (the owner's). In a background window computer-tool clicks on the material
radios did nothing and `form_input` on the native inputs did not update the form ("Select app or game" stayed):
click the inner `[role=radio]` with a JS click, then check `aria-checked="true"` and that no "Select …" hint is
left. Text inputs set by `form_input` are fine. After Create app the app lives at
`/console/u/0/developers/<developerId>/app/<appId>/app-dashboard`: put the id in `play.appId`.
- **After Play Create app, an owner step:** a service account's app-level permissions do NOT cover apps created
later. The owner opens Users and permissions > the service account > Add app > the new app > Admin (or the minimal
set the plan lists) > Apply > Save changes, then `storebound apps check --store play`. Never do it yourself (a
permission grant; auto mode blocks it too).
## Optional: the scripted fast path (`storebound console fill`)
`console fill` drives a visible browser by itself with the same answers and click rules. It is fast when the page
matches its model; when it stalls on a changed page, switch to the agent-first mode above instead of waiting for a
fix. It is not available over MCP (the owner runs it in a terminal or the desktop app).
## Forms
@ -28,7 +89,7 @@ It is not available over MCP.
| `play-content-rating` | Policy > App content > Content rating | app.contactEmail, app.profile, products, console.contentRating |
| `play-target-audience` | Policy > App content > Target audience and content (+ Ads) | console.targetAudience, ads.appAdsTxt |
## Steps
## Steps (scripted fast path)
1. `storebound console fill` lists the forms. `storebound console fill <form> --dry` prints every answer with its
source; `[check]` lines are not proven by the config. Show them to the owner.
@ -127,7 +188,7 @@ It is not available over MCP.
for the owner to pick).
6. Multi-page forms: storebound fills a page and clicks its Next itself (App Privacy: Get Started or Edit next to
Data Types, Next, the data types' Save, then "Set Up <type>" for each collected type in the Data Types section:
purposes > Next > linked > Next > tracking > Save; a dialog step it does not know: a debug dump and
purposes > Next > linked > Next > two information pages > Next > Next > tracking > Save; a dialog step it does not know: a debug dump and
`paused on "<type>"` until the owner answered it; content rating: Save draft, then Next). It stops on a page only when an answer there is uncertain: it logs
`answer needed on "<page>": <the answers>`, leaves them outlined, and goes on by itself once the owner has set
each one (a box that should stay empty: click it twice). It never clicks Next past an open question.
@ -160,8 +221,11 @@ It is not available over MCP.
owner before they press Create app.
- **Declarations** (Developer Program Policies, US export laws) are agreements: storebound never ticks them, it
outlines them. The owner reads and ticks them and presses Create app.
- The package name is not in this form: the first AAB upload sets it for good (`storebound play upload --track
internal`, or `storebound flow run release`).
- App package name (`play.packageName`, max 150) is in the form: storebound fills it and presses the read-only
"Check availability" ("Package name available"). It is fixed for good once the app is created.
- App or game and Free or paid are `<material-radio>`s: storebound clicks the inner `[role=radio]` (the native input
does not update the form's model). With `play.developerId` the form opens by its own URL (`.../create-new-app`).
- After Create app: the owner adds the new app to the service account (see "Verified UI facts" above).
## What storebound clicks, and what stays with the owner
@ -171,10 +235,10 @@ content", "Create and set up your app"):
| form | storebound clicks (navigation) | stays with the owner, and why |
|---|---|---|
| App Privacy | Get Started; Edit next to Data Types (never the Privacy Policy Edit; skipped when the section already lists exactly the config's types); "Set Up <type>" for each collected type (a plain text, clicked by its exact text); a type's own Edit only when its purposes differ from the config; Next; **Save inside the questionnaire dialogs** (a draft: Apple publishes the answers only after Publish) | **Publish** and its confirmation: it puts the answers on the App Store product page; the "?" help buttons are never clicked |
| App Privacy | Get Started; Edit next to Data Types (never the Privacy Policy Edit; skipped when the section already lists exactly the config's types); "Set Up <type>" for each collected type (a plain text, clicked by its exact text); a type's own Edit only when its purposes differ from the config; Next; **Save inside the questionnaire dialogs** (a draft: Apple publishes the answers only after Publish) | **Publish** and its confirmation: it puts the answers on the App Store product page; the "?" help buttons and "Definitions and Examples" are never clicked |
| New App (App Store) | + and New App (Cancel only to leave a team without the bundle id) | **Create**: creates the app record for good |
| Age rating (guide only) | nothing (`storebound apple appinfo` sets it by API) | Set Up / Next / Done, if the owner wants to look |
| Create app (Play) | Create app on the app list (opens the form) | the two **declarations** (agreements, never ticked) and **Create app** in the form: creates the app |
| Create app (Play) | Create app on the app list (opens the form); Check availability next to the package name (read-only) | the two **declarations** (agreements, never ticked) and **Create app** in the form: creates the app |
| Content rating (Play) | Start; **Save draft** then Next on each page (a draft: IARC gets nothing before Submit; the owner agreed) | **Submit** on the Summary: sends the questionnaire to IARC |
| Target audience (Play) | Start / Manage, Next between the pages | **Save** on the last page: stores the declaration, which Google then reviews |