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:
parent
a9261a8052
commit
c9a7f095c4
34 changed files with 1430 additions and 113 deletions
|
|
@ -72,10 +72,10 @@ export function formMeta(id: FormId, config: ShipConfig): FormMeta {
|
|||
open: ['General > App Information > Age Ratings > Set Up Age Ratings (only to look: `storebound apple appinfo` sets it)'] };
|
||||
case 'apple-app-privacy': return { id, store: 'apple', title: 'App Store Connect: App Privacy', url: privacy, stopBefore: 'Publish', fillable: true,
|
||||
open: [...(config.apple?.appId ? [] : ['Apps > your app (set apple.appId so storebound opens it directly)']), 'App Privacy in the sidebar (storebound clicks Get Started, or Edit next to Data Types, and walks the questionnaire itself)'] };
|
||||
case 'play-app-record': return { id, store: 'play', title: 'Play Console: Create app', url: PLAY, stopBefore: 'Create app', fillable: true,
|
||||
open: ['Pick the developer account if Play Console asks (play.developerId or play.developerAccount picks it)', 'Home (All apps) > Create app'],
|
||||
case 'play-app-record': return { id, store: 'play', title: 'Play Console: Create app', url: config.play?.developerId ? `${PLAY}/u/0/developers/${encodeURIComponent(config.play.developerId)}/create-new-app` : PLAY, stopBefore: 'Create app', fillable: true,
|
||||
open: config.play?.developerId ? ['the Create app form of the developer account opens by link (/developers/<play.developerId>/create-new-app)'] : ['Pick the developer account if Play Console asks (play.developerId or play.developerAccount picks it)', 'Home (All apps) > Create app (or /console/u/0/developers/<developer id>/create-new-app)'],
|
||||
notes: [
|
||||
'The package name is not part of this form: the first AAB upload sets it for good (storebound play upload --track internal, or storebound flow run release).',
|
||||
'The form has an App package name field (play.packageName, at most 150 characters): storebound fills it and presses "Check availability" (read-only), which should say "Package name available". The package name is fixed for good once the app is created.',
|
||||
'Free or paid is an owner check: a free app can never become paid later on Google Play.',
|
||||
'The Developer Program Policies and US export laws boxes are agreements: storebound never ticks them. Read and tick them yourself, then press Create app.',
|
||||
] };
|
||||
|
|
@ -138,6 +138,8 @@ export const playLanguageLabel = (code: string): string | null => (PLAY_LANGUAGE
|
|||
|
||||
/** The Play app name limit (Create app form and store listing title). */
|
||||
export const PLAY_NAME_MAX = 30;
|
||||
/** The Create app form's App package name limit (verified 2026-10-12). */
|
||||
export const PLAY_PACKAGE_MAX = 150;
|
||||
|
||||
function playAppRecord(config: ShipConfig): Answer[] {
|
||||
const p = config.play;
|
||||
|
|
@ -150,9 +152,12 @@ function playAppRecord(config: ShipConfig): Answer[] {
|
|||
const profile = config.app.profile;
|
||||
const sells = (config.products?.length ?? 0) > 0 || (config.subscriptions?.length ?? 0) > 0, ads = (config.ads?.appAdsTxt?.length ?? 0) > 0;
|
||||
const once = 'A free app can never become paid later on Google Play (a paid app can become free).';
|
||||
const pkg = p?.packageName;
|
||||
const out: Answer[] = [
|
||||
len <= PLAY_NAME_MAX ? ok('name', 'App name', name, nameSrc, 'Shown on Google Play; the store listing can change it later.')
|
||||
: ask('name', 'App name', nameSrc, `"${name}" is ${len} characters; Play allows ${PLAY_NAME_MAX}. Set play.name to a shorter name.`),
|
||||
pkg && pkg.length <= PLAY_PACKAGE_MAX ? ok('packageName', 'App package name', pkg, 'play.packageName', 'Fixed for good once the app is created. Press "Check availability" next to it (read-only): "Package name available".')
|
||||
: ask('packageName', 'App package name', 'play.packageName', pkg ? `"${pkg}" is longer than ${PLAY_PACKAGE_MAX} characters.` : 'Set play.packageName (the applicationId of the Android build): it is fixed for good once the app is created.'),
|
||||
lang ? ok('language', 'Default language', lang, langSrc)
|
||||
: ask('language', 'Default language', 'play.defaultLanguage', code ? `Pick the language of code "${code}" (storebound does not know its Play Console name).` : 'Set play.defaultLanguage (e.g. en-US) or a play code on the first language.'),
|
||||
profile ? ok('type', 'App or game', profile === 'game' ? 'Game' : 'App', 'app.profile', 'Changeable later in the store settings.')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue