agent rules: first rule "Do it, don't ask" (agents-core and every adapter, README, store-pitfalls lead, first-release, declarations and console skills); the agent runs the real command after the dry run, the owner presses only final public or irreversible buttons and answers compliance facts in one batch; handoff text removed from skills; tests/do-it-dont-ask.test.ts. Pitfall 26
This commit is contained in:
parent
fc524cd2d4
commit
dfc28c15f8
22 changed files with 393 additions and 105 deletions
|
|
@ -7,16 +7,43 @@ alwaysApply: false
|
|||
|
||||
These rules apply to every AI tool that uses storebound (skills, MCP server or the CLI in a terminal).
|
||||
|
||||
## First rule: do it, don't ask
|
||||
|
||||
storebound plus you, the AI agent, do the work. The owner is not your pair of hands.
|
||||
|
||||
1. **You do everything yourself:** API calls, uploads, builds, template and CSV downloads and exports, every console
|
||||
navigation (open, Get Started, Edit, Next, Continue, Save draft), console forms, and the verification afterwards.
|
||||
Never tell the owner "run this yourself" or "click X yourself" for any of these.
|
||||
2. **The owner keeps only the final public or irreversible buttons:** Submit for review (App Review or Beta App
|
||||
Review), releasing a version or completing / resuming a production rollout, App Privacy Publish, accepting legal
|
||||
agreements; plus deleting store data, changing live prices, sending review replies and inviting or removing
|
||||
testers. (Also the owner's: canceling a submission, starting or stopping a store experiment, a console form's final
|
||||
Submit / Create that a console plan lists in `buttons.final`, signing in and granting account permissions.) For
|
||||
these you prepare everything, show the dry run, and the owner presses one button or says yes.
|
||||
3. **Ask the owner only for facts that no code, config or doc can prove:** compliance answers such as Data safety,
|
||||
App Privacy, age rating, export compliance, partial data deletion. Collect ALL of them in ONE batch at the start
|
||||
(`storebound check` and `storebound validate` list them), never one at a time during the run. Reuse answers that
|
||||
are already in the config.
|
||||
4. **Default loop:** plan, then you drive (the API first, your browser tool for consoles without an API), then verify
|
||||
(read it back), then continue. No round trip to the owner in between.
|
||||
5. **Catch rejections offline.** Before a write, `storebound check` and `--dry` must catch what the store would refuse
|
||||
(live-shape fixtures, id and pair checks). A failure belongs in the dry run, not in a 400 at write time; when a
|
||||
store refuses something the dry run passed, fix the check (pitfalls), not just the data.
|
||||
|
||||
Every hour of "please click this" is an hour the owner did not want to spend. If you catch yourself writing "you
|
||||
need to ...", do it instead, unless it is one of the owner steps in point 2.
|
||||
|
||||
## The other rules
|
||||
|
||||
**Read `skills/store-pitfalls/SKILL.md` before any store task.** It lists the mistakes already made in real releases
|
||||
(store lists that lag after a create, dry runs without a plan, taken App Store names, byte limits, ...) and what to do.
|
||||
|
||||
1. **The owner decides public and irreversible steps.** Submitting for review (App Review or Beta App Review),
|
||||
releasing a version, resuming or completing a rollout, canceling a submission, deleting products or listings,
|
||||
accepting agreements, sending review replies, inviting or removing testers, changing prices, starting or stopping
|
||||
a store experiment: explain what will happen and let the owner do it (or run the command only after a clear yes in
|
||||
chat). storebound's MCP server does not offer these at all.
|
||||
2. **Dry run first.** Every write command has `--dry` (MCP: `dry_run`, default true). Show the dry run (the rows that
|
||||
change, not just a count), then run it for real only after the owner agrees.
|
||||
1. **The owner presses only the owner steps** (point 2 of the first rule). Prepare them completely, say what will
|
||||
happen, and let the owner press the button, or run the command only after a clear yes in chat. storebound's MCP
|
||||
server does not offer these at all. Everything else you run yourself.
|
||||
2. **Dry run first, then run it yourself.** Every write command has `--dry` (MCP: `dry_run`, default true). Run the
|
||||
dry run, check and show it (the rows that change, not just a count), then run the real command yourself (`--yes`
|
||||
where it asks for a confirmation) and read the result back. Wait for the owner's yes only before an owner step.
|
||||
3. **Read before you write.** `storebound scan` (offline: rejection risks in the project itself), `storebound check`
|
||||
(offline) and `storebound validate` (read-only, both stores) tell you what is missing and in which order to fix it.
|
||||
4. **Credentials only from the environment, `.storebound/`** in the project (gitignored) **or a credential profile**
|
||||
|
|
@ -24,7 +51,8 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
passwords or tokens in chat, never print them, never write them into the config, docs or commits. The same goes
|
||||
for the App Review demo account (`reviewDemoAccount` in `.storebound/credentials.json`): the owner puts it there.
|
||||
5. **Never answer a compliance question you cannot know.** Export compliance, Data safety, App Privacy, age rating,
|
||||
target audience: ask the owner when the code does not prove the answer. A wrong "no" is worse than a slow "ask".
|
||||
target audience: ask the owner when the code does not prove the answer, all such questions in one batch at the
|
||||
start (first rule, point 3), and write the answers into the config. A wrong "no" is worse than a slow "ask".
|
||||
6. **Pick builds by explicit number.** Use the build number / versionCode you just uploaded, never "the latest".
|
||||
7. **Long uploads run in the background with a log** (`storebound play images > .storebound/images.log 2>&1 &`) and
|
||||
you report the progress lines, not guesses.
|
||||
|
|
@ -36,7 +64,7 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
10. **Console forms without an API: drive them yourself, agent-first.** `storebound console plan <form> --json` (MCP
|
||||
`console_plan`) gives the start URL, steps, the answer sheet, the buttons you must never press and the verified UI
|
||||
facts. Drive the page with your own browser tool, adapt to what it shows, run long flows as an in-page async loop
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop before the final button (Publish,
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop only before the final button (Publish,
|
||||
Submit, Create, a final Save) and tell the owner exactly what to press, then `storebound console verify <form>`.
|
||||
Never sign in, accept an agreement or grant a permission (a service account's app access) for the owner.
|
||||
`storebound console fill` is the optional scripted fast path; it never blocks you.
|
||||
|
|
|
|||
46
.github/copilot-instructions.md
vendored
46
.github/copilot-instructions.md
vendored
|
|
@ -7,16 +7,43 @@ format; `storebound install --agent copilot` copies them to `.github/skills/` of
|
|||
|
||||
These rules apply to every AI tool that uses storebound (skills, MCP server or the CLI in a terminal).
|
||||
|
||||
## First rule: do it, don't ask
|
||||
|
||||
storebound plus you, the AI agent, do the work. The owner is not your pair of hands.
|
||||
|
||||
1. **You do everything yourself:** API calls, uploads, builds, template and CSV downloads and exports, every console
|
||||
navigation (open, Get Started, Edit, Next, Continue, Save draft), console forms, and the verification afterwards.
|
||||
Never tell the owner "run this yourself" or "click X yourself" for any of these.
|
||||
2. **The owner keeps only the final public or irreversible buttons:** Submit for review (App Review or Beta App
|
||||
Review), releasing a version or completing / resuming a production rollout, App Privacy Publish, accepting legal
|
||||
agreements; plus deleting store data, changing live prices, sending review replies and inviting or removing
|
||||
testers. (Also the owner's: canceling a submission, starting or stopping a store experiment, a console form's final
|
||||
Submit / Create that a console plan lists in `buttons.final`, signing in and granting account permissions.) For
|
||||
these you prepare everything, show the dry run, and the owner presses one button or says yes.
|
||||
3. **Ask the owner only for facts that no code, config or doc can prove:** compliance answers such as Data safety,
|
||||
App Privacy, age rating, export compliance, partial data deletion. Collect ALL of them in ONE batch at the start
|
||||
(`storebound check` and `storebound validate` list them), never one at a time during the run. Reuse answers that
|
||||
are already in the config.
|
||||
4. **Default loop:** plan, then you drive (the API first, your browser tool for consoles without an API), then verify
|
||||
(read it back), then continue. No round trip to the owner in between.
|
||||
5. **Catch rejections offline.** Before a write, `storebound check` and `--dry` must catch what the store would refuse
|
||||
(live-shape fixtures, id and pair checks). A failure belongs in the dry run, not in a 400 at write time; when a
|
||||
store refuses something the dry run passed, fix the check (pitfalls), not just the data.
|
||||
|
||||
Every hour of "please click this" is an hour the owner did not want to spend. If you catch yourself writing "you
|
||||
need to ...", do it instead, unless it is one of the owner steps in point 2.
|
||||
|
||||
## The other rules
|
||||
|
||||
**Read `skills/store-pitfalls/SKILL.md` before any store task.** It lists the mistakes already made in real releases
|
||||
(store lists that lag after a create, dry runs without a plan, taken App Store names, byte limits, ...) and what to do.
|
||||
|
||||
1. **The owner decides public and irreversible steps.** Submitting for review (App Review or Beta App Review),
|
||||
releasing a version, resuming or completing a rollout, canceling a submission, deleting products or listings,
|
||||
accepting agreements, sending review replies, inviting or removing testers, changing prices, starting or stopping
|
||||
a store experiment: explain what will happen and let the owner do it (or run the command only after a clear yes in
|
||||
chat). storebound's MCP server does not offer these at all.
|
||||
2. **Dry run first.** Every write command has `--dry` (MCP: `dry_run`, default true). Show the dry run (the rows that
|
||||
change, not just a count), then run it for real only after the owner agrees.
|
||||
1. **The owner presses only the owner steps** (point 2 of the first rule). Prepare them completely, say what will
|
||||
happen, and let the owner press the button, or run the command only after a clear yes in chat. storebound's MCP
|
||||
server does not offer these at all. Everything else you run yourself.
|
||||
2. **Dry run first, then run it yourself.** Every write command has `--dry` (MCP: `dry_run`, default true). Run the
|
||||
dry run, check and show it (the rows that change, not just a count), then run the real command yourself (`--yes`
|
||||
where it asks for a confirmation) and read the result back. Wait for the owner's yes only before an owner step.
|
||||
3. **Read before you write.** `storebound scan` (offline: rejection risks in the project itself), `storebound check`
|
||||
(offline) and `storebound validate` (read-only, both stores) tell you what is missing and in which order to fix it.
|
||||
4. **Credentials only from the environment, `.storebound/`** in the project (gitignored) **or a credential profile**
|
||||
|
|
@ -24,7 +51,8 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
passwords or tokens in chat, never print them, never write them into the config, docs or commits. The same goes
|
||||
for the App Review demo account (`reviewDemoAccount` in `.storebound/credentials.json`): the owner puts it there.
|
||||
5. **Never answer a compliance question you cannot know.** Export compliance, Data safety, App Privacy, age rating,
|
||||
target audience: ask the owner when the code does not prove the answer. A wrong "no" is worse than a slow "ask".
|
||||
target audience: ask the owner when the code does not prove the answer, all such questions in one batch at the
|
||||
start (first rule, point 3), and write the answers into the config. A wrong "no" is worse than a slow "ask".
|
||||
6. **Pick builds by explicit number.** Use the build number / versionCode you just uploaded, never "the latest".
|
||||
7. **Long uploads run in the background with a log** (`storebound play images > .storebound/images.log 2>&1 &`) and
|
||||
you report the progress lines, not guesses.
|
||||
|
|
@ -36,7 +64,7 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
10. **Console forms without an API: drive them yourself, agent-first.** `storebound console plan <form> --json` (MCP
|
||||
`console_plan`) gives the start URL, steps, the answer sheet, the buttons you must never press and the verified UI
|
||||
facts. Drive the page with your own browser tool, adapt to what it shows, run long flows as an in-page async loop
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop before the final button (Publish,
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop only before the final button (Publish,
|
||||
Submit, Create, a final Save) and tell the owner exactly what to press, then `storebound console verify <form>`.
|
||||
Never sign in, accept an agreement or grant a permission (a service account's app access) for the owner.
|
||||
`storebound console fill` is the optional scripted fast path; it never blocks you.
|
||||
|
|
|
|||
46
AGENTS.md
46
AGENTS.md
|
|
@ -8,16 +8,43 @@ file below and follow it step by step.
|
|||
|
||||
These rules apply to every AI tool that uses storebound (skills, MCP server or the CLI in a terminal).
|
||||
|
||||
## First rule: do it, don't ask
|
||||
|
||||
storebound plus you, the AI agent, do the work. The owner is not your pair of hands.
|
||||
|
||||
1. **You do everything yourself:** API calls, uploads, builds, template and CSV downloads and exports, every console
|
||||
navigation (open, Get Started, Edit, Next, Continue, Save draft), console forms, and the verification afterwards.
|
||||
Never tell the owner "run this yourself" or "click X yourself" for any of these.
|
||||
2. **The owner keeps only the final public or irreversible buttons:** Submit for review (App Review or Beta App
|
||||
Review), releasing a version or completing / resuming a production rollout, App Privacy Publish, accepting legal
|
||||
agreements; plus deleting store data, changing live prices, sending review replies and inviting or removing
|
||||
testers. (Also the owner's: canceling a submission, starting or stopping a store experiment, a console form's final
|
||||
Submit / Create that a console plan lists in `buttons.final`, signing in and granting account permissions.) For
|
||||
these you prepare everything, show the dry run, and the owner presses one button or says yes.
|
||||
3. **Ask the owner only for facts that no code, config or doc can prove:** compliance answers such as Data safety,
|
||||
App Privacy, age rating, export compliance, partial data deletion. Collect ALL of them in ONE batch at the start
|
||||
(`storebound check` and `storebound validate` list them), never one at a time during the run. Reuse answers that
|
||||
are already in the config.
|
||||
4. **Default loop:** plan, then you drive (the API first, your browser tool for consoles without an API), then verify
|
||||
(read it back), then continue. No round trip to the owner in between.
|
||||
5. **Catch rejections offline.** Before a write, `storebound check` and `--dry` must catch what the store would refuse
|
||||
(live-shape fixtures, id and pair checks). A failure belongs in the dry run, not in a 400 at write time; when a
|
||||
store refuses something the dry run passed, fix the check (pitfalls), not just the data.
|
||||
|
||||
Every hour of "please click this" is an hour the owner did not want to spend. If you catch yourself writing "you
|
||||
need to ...", do it instead, unless it is one of the owner steps in point 2.
|
||||
|
||||
## The other rules
|
||||
|
||||
**Read `skills/store-pitfalls/SKILL.md` before any store task.** It lists the mistakes already made in real releases
|
||||
(store lists that lag after a create, dry runs without a plan, taken App Store names, byte limits, ...) and what to do.
|
||||
|
||||
1. **The owner decides public and irreversible steps.** Submitting for review (App Review or Beta App Review),
|
||||
releasing a version, resuming or completing a rollout, canceling a submission, deleting products or listings,
|
||||
accepting agreements, sending review replies, inviting or removing testers, changing prices, starting or stopping
|
||||
a store experiment: explain what will happen and let the owner do it (or run the command only after a clear yes in
|
||||
chat). storebound's MCP server does not offer these at all.
|
||||
2. **Dry run first.** Every write command has `--dry` (MCP: `dry_run`, default true). Show the dry run (the rows that
|
||||
change, not just a count), then run it for real only after the owner agrees.
|
||||
1. **The owner presses only the owner steps** (point 2 of the first rule). Prepare them completely, say what will
|
||||
happen, and let the owner press the button, or run the command only after a clear yes in chat. storebound's MCP
|
||||
server does not offer these at all. Everything else you run yourself.
|
||||
2. **Dry run first, then run it yourself.** Every write command has `--dry` (MCP: `dry_run`, default true). Run the
|
||||
dry run, check and show it (the rows that change, not just a count), then run the real command yourself (`--yes`
|
||||
where it asks for a confirmation) and read the result back. Wait for the owner's yes only before an owner step.
|
||||
3. **Read before you write.** `storebound scan` (offline: rejection risks in the project itself), `storebound check`
|
||||
(offline) and `storebound validate` (read-only, both stores) tell you what is missing and in which order to fix it.
|
||||
4. **Credentials only from the environment, `.storebound/`** in the project (gitignored) **or a credential profile**
|
||||
|
|
@ -25,7 +52,8 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
passwords or tokens in chat, never print them, never write them into the config, docs or commits. The same goes
|
||||
for the App Review demo account (`reviewDemoAccount` in `.storebound/credentials.json`): the owner puts it there.
|
||||
5. **Never answer a compliance question you cannot know.** Export compliance, Data safety, App Privacy, age rating,
|
||||
target audience: ask the owner when the code does not prove the answer. A wrong "no" is worse than a slow "ask".
|
||||
target audience: ask the owner when the code does not prove the answer, all such questions in one batch at the
|
||||
start (first rule, point 3), and write the answers into the config. A wrong "no" is worse than a slow "ask".
|
||||
6. **Pick builds by explicit number.** Use the build number / versionCode you just uploaded, never "the latest".
|
||||
7. **Long uploads run in the background with a log** (`storebound play images > .storebound/images.log 2>&1 &`) and
|
||||
you report the progress lines, not guesses.
|
||||
|
|
@ -37,7 +65,7 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
10. **Console forms without an API: drive them yourself, agent-first.** `storebound console plan <form> --json` (MCP
|
||||
`console_plan`) gives the start URL, steps, the answer sheet, the buttons you must never press and the verified UI
|
||||
facts. Drive the page with your own browser tool, adapt to what it shows, run long flows as an in-page async loop
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop before the final button (Publish,
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop only before the final button (Publish,
|
||||
Submit, Create, a final Save) and tell the owner exactly what to press, then `storebound console verify <form>`.
|
||||
Never sign in, accept an agreement or grant a permission (a service account's app access) for the owner.
|
||||
`storebound console fill` is the optional scripted fast path; it never blocks you.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
- Agent rules: a first, top-level rule "Do it, don't ask" in `docs/agents-core.md` (and so AGENTS.md, GEMINI.md,
|
||||
the Copilot and Cursor rules), README ("How agents use storebound"), the store-pitfalls skill and the openings of
|
||||
console-autofill, play-first-release, appstore-first-release and store-declarations. The agent does API calls,
|
||||
uploads, builds, exports, console navigation and forms itself and runs the real command after the dry run; the
|
||||
owner presses only the final public or irreversible buttons and answers the facts no file proves in one batch at
|
||||
the start. Skill text that left navigation, draft saves, exports or uploads to the owner is rewritten;
|
||||
`tests/do-it-dont-ask.test.ts` guards it. Pitfall 26.
|
||||
- Fix (`play build`): the Android SDK is found the way Android Studio finds it, so a non-interactive shell (no
|
||||
`ANDROID_HOME`) with a gitignored `local.properties` no longer ends in Gradle's "SDK location not found". Order:
|
||||
`ANDROID_HOME`, `ANDROID_SDK_ROOT`, `sdk.dir` in the Gradle project's `local.properties`, then
|
||||
|
|
|
|||
46
GEMINI.md
46
GEMINI.md
|
|
@ -6,16 +6,43 @@ This extension ships Agent Skills (skills/) and the storebound MCP server for mo
|
|||
|
||||
These rules apply to every AI tool that uses storebound (skills, MCP server or the CLI in a terminal).
|
||||
|
||||
## First rule: do it, don't ask
|
||||
|
||||
storebound plus you, the AI agent, do the work. The owner is not your pair of hands.
|
||||
|
||||
1. **You do everything yourself:** API calls, uploads, builds, template and CSV downloads and exports, every console
|
||||
navigation (open, Get Started, Edit, Next, Continue, Save draft), console forms, and the verification afterwards.
|
||||
Never tell the owner "run this yourself" or "click X yourself" for any of these.
|
||||
2. **The owner keeps only the final public or irreversible buttons:** Submit for review (App Review or Beta App
|
||||
Review), releasing a version or completing / resuming a production rollout, App Privacy Publish, accepting legal
|
||||
agreements; plus deleting store data, changing live prices, sending review replies and inviting or removing
|
||||
testers. (Also the owner's: canceling a submission, starting or stopping a store experiment, a console form's final
|
||||
Submit / Create that a console plan lists in `buttons.final`, signing in and granting account permissions.) For
|
||||
these you prepare everything, show the dry run, and the owner presses one button or says yes.
|
||||
3. **Ask the owner only for facts that no code, config or doc can prove:** compliance answers such as Data safety,
|
||||
App Privacy, age rating, export compliance, partial data deletion. Collect ALL of them in ONE batch at the start
|
||||
(`storebound check` and `storebound validate` list them), never one at a time during the run. Reuse answers that
|
||||
are already in the config.
|
||||
4. **Default loop:** plan, then you drive (the API first, your browser tool for consoles without an API), then verify
|
||||
(read it back), then continue. No round trip to the owner in between.
|
||||
5. **Catch rejections offline.** Before a write, `storebound check` and `--dry` must catch what the store would refuse
|
||||
(live-shape fixtures, id and pair checks). A failure belongs in the dry run, not in a 400 at write time; when a
|
||||
store refuses something the dry run passed, fix the check (pitfalls), not just the data.
|
||||
|
||||
Every hour of "please click this" is an hour the owner did not want to spend. If you catch yourself writing "you
|
||||
need to ...", do it instead, unless it is one of the owner steps in point 2.
|
||||
|
||||
## The other rules
|
||||
|
||||
**Read `skills/store-pitfalls/SKILL.md` before any store task.** It lists the mistakes already made in real releases
|
||||
(store lists that lag after a create, dry runs without a plan, taken App Store names, byte limits, ...) and what to do.
|
||||
|
||||
1. **The owner decides public and irreversible steps.** Submitting for review (App Review or Beta App Review),
|
||||
releasing a version, resuming or completing a rollout, canceling a submission, deleting products or listings,
|
||||
accepting agreements, sending review replies, inviting or removing testers, changing prices, starting or stopping
|
||||
a store experiment: explain what will happen and let the owner do it (or run the command only after a clear yes in
|
||||
chat). storebound's MCP server does not offer these at all.
|
||||
2. **Dry run first.** Every write command has `--dry` (MCP: `dry_run`, default true). Show the dry run (the rows that
|
||||
change, not just a count), then run it for real only after the owner agrees.
|
||||
1. **The owner presses only the owner steps** (point 2 of the first rule). Prepare them completely, say what will
|
||||
happen, and let the owner press the button, or run the command only after a clear yes in chat. storebound's MCP
|
||||
server does not offer these at all. Everything else you run yourself.
|
||||
2. **Dry run first, then run it yourself.** Every write command has `--dry` (MCP: `dry_run`, default true). Run the
|
||||
dry run, check and show it (the rows that change, not just a count), then run the real command yourself (`--yes`
|
||||
where it asks for a confirmation) and read the result back. Wait for the owner's yes only before an owner step.
|
||||
3. **Read before you write.** `storebound scan` (offline: rejection risks in the project itself), `storebound check`
|
||||
(offline) and `storebound validate` (read-only, both stores) tell you what is missing and in which order to fix it.
|
||||
4. **Credentials only from the environment, `.storebound/`** in the project (gitignored) **or a credential profile**
|
||||
|
|
@ -23,7 +50,8 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
passwords or tokens in chat, never print them, never write them into the config, docs or commits. The same goes
|
||||
for the App Review demo account (`reviewDemoAccount` in `.storebound/credentials.json`): the owner puts it there.
|
||||
5. **Never answer a compliance question you cannot know.** Export compliance, Data safety, App Privacy, age rating,
|
||||
target audience: ask the owner when the code does not prove the answer. A wrong "no" is worse than a slow "ask".
|
||||
target audience: ask the owner when the code does not prove the answer, all such questions in one batch at the
|
||||
start (first rule, point 3), and write the answers into the config. A wrong "no" is worse than a slow "ask".
|
||||
6. **Pick builds by explicit number.** Use the build number / versionCode you just uploaded, never "the latest".
|
||||
7. **Long uploads run in the background with a log** (`storebound play images > .storebound/images.log 2>&1 &`) and
|
||||
you report the progress lines, not guesses.
|
||||
|
|
@ -35,7 +63,7 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
10. **Console forms without an API: drive them yourself, agent-first.** `storebound console plan <form> --json` (MCP
|
||||
`console_plan`) gives the start URL, steps, the answer sheet, the buttons you must never press and the verified UI
|
||||
facts. Drive the page with your own browser tool, adapt to what it shows, run long flows as an in-page async loop
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop before the final button (Publish,
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop only before the final button (Publish,
|
||||
Submit, Create, a final Save) and tell the owner exactly what to press, then `storebound console verify <form>`.
|
||||
Never sign in, accept an agreement or grant a permission (a service account's app access) for the owner.
|
||||
`storebound console fill` is the optional scripted fast path; it never blocks you.
|
||||
|
|
|
|||
29
README.md
29
README.md
|
|
@ -28,6 +28,23 @@ No account, no sign-up, no telemetry. A small Bun CLI that talks to the official
|
|||
Agent Skills that walk your AI coding tool (or you) through the parts that are still console clicks, and an MCP server
|
||||
so agents can call the CLI safely. **storebound never presses Submit, Release or Publish for you.**
|
||||
|
||||
## How agents use storebound
|
||||
|
||||
**Do it, don't ask.** Your AI agent and storebound do the work: API calls, uploads, builds, CSV and template
|
||||
exports, every console page (open, Get Started, Edit, Next, Save draft), console forms and the check afterwards. You
|
||||
are not asked to click through consoles or run commands one by one.
|
||||
|
||||
- **You press only the final public or irreversible buttons:** Submit for review, releasing a version or a production
|
||||
rollout, App Privacy Publish, legal agreements; plus deleting store data, changing live prices, sending review
|
||||
replies and inviting or removing testers. The agent prepares each one and shows you the dry run first.
|
||||
- **You answer only what no file can prove** (Data safety, App Privacy, age rating, export compliance, partial
|
||||
deletion): all of it in one batch at the start (`storebound check` / `validate` list the questions), saved in the
|
||||
config so nobody asks again.
|
||||
- **The loop:** plan, the agent drives (API first, its browser for consoles without an API), verify by reading back,
|
||||
continue. `check` and `--dry` catch what a store would refuse before anything is written.
|
||||
|
||||
The full rules are in [AGENTS.md](AGENTS.md) (generated from `docs/agents-core.md`).
|
||||
|
||||
Pick a profile and start from honest templates: `init --profile app` (utility / productivity app, optional account,
|
||||
analytics, no ads; the default), `--profile subscription-app` (accounts + auto-renewable subscriptions) or
|
||||
`--profile game` (free-to-play with ads and IAP).
|
||||
|
|
@ -497,8 +514,8 @@ a terminal first and are never offered over MCP.
|
|||
visible browser, goes to the form by itself (Apps > + > New App, the app's App Privacy, Play All apps > Create app,
|
||||
Play app list > App content > Start / Manage;
|
||||
navigation clicks only, never Save / Submit / Publish / Create / Next), fills what the config proves, highlights the
|
||||
rest and stops before the final button: you click. **Sign-in:** storebound's own profile
|
||||
(one per store, `~/.storebound/console-profile/<store>`): you sign in there once by hand, it is kept between runs
|
||||
rest and stops before the final button: you press it. **Sign-in:** storebound's own profile
|
||||
(one per store, `~/.storebound/console-profile/<store>`): you sign in there once, it is kept between runs
|
||||
(session restore on launch, graceful close; tick "Keep me signed in" / "Stay signed in"). storebound starts that
|
||||
Chrome itself as a normal window (no `--enable-automation`, `navigator.webdriver` false) so Google accepts the
|
||||
sign-in; if Google still answers `/signin/rejected` it says so. A Chrome running with remote debugging is used in
|
||||
|
|
@ -518,9 +535,11 @@ a terminal first and are never offered over MCP.
|
|||
declarations and never presses the form's Create app: you do. With `play.developerId` it opens the form's own URL
|
||||
(`/console/u/0/developers/<id>/create-new-app`); it fills App package name from `play.packageName` and presses the
|
||||
read-only "Check availability", and clicks the inner `[role=radio]` of Play's material radios (the native input
|
||||
does not update the form). After Create app, add the new app to your service account yourself (Users and
|
||||
permissions > the service account > Add app): app-level permissions do not cover apps created later.
|
||||
When a page has changed it falls back to step-by-step guidance with copyable answers. **Console pages change; this is AI-assisted: review every field and save it yourself.** Desktop: "Fill in
|
||||
does not update the form). After Create app, grant your service account access to the new app (Users and
|
||||
permissions > the service account > Add app; a permission grant, so it is yours): app-level permissions do not
|
||||
cover apps created later. When a page has changed, your agent drives that part with its browser tool from
|
||||
`storebound console plan`. **Console pages change; this is AI-assisted: review every field before you press the
|
||||
final button.** Desktop: "Fill in
|
||||
console" on the App info tab. Never over MCP. Skill: `console-autofill`.
|
||||
|
||||
MCP gets only the safe parts: `prices_ppp`, `web_init`, `apple_adhoc_options` (local files, dry run by default) and
|
||||
|
|
|
|||
|
|
@ -2,16 +2,43 @@
|
|||
|
||||
These rules apply to every AI tool that uses storebound (skills, MCP server or the CLI in a terminal).
|
||||
|
||||
## First rule: do it, don't ask
|
||||
|
||||
storebound plus you, the AI agent, do the work. The owner is not your pair of hands.
|
||||
|
||||
1. **You do everything yourself:** API calls, uploads, builds, template and CSV downloads and exports, every console
|
||||
navigation (open, Get Started, Edit, Next, Continue, Save draft), console forms, and the verification afterwards.
|
||||
Never tell the owner "run this yourself" or "click X yourself" for any of these.
|
||||
2. **The owner keeps only the final public or irreversible buttons:** Submit for review (App Review or Beta App
|
||||
Review), releasing a version or completing / resuming a production rollout, App Privacy Publish, accepting legal
|
||||
agreements; plus deleting store data, changing live prices, sending review replies and inviting or removing
|
||||
testers. (Also the owner's: canceling a submission, starting or stopping a store experiment, a console form's final
|
||||
Submit / Create that a console plan lists in `buttons.final`, signing in and granting account permissions.) For
|
||||
these you prepare everything, show the dry run, and the owner presses one button or says yes.
|
||||
3. **Ask the owner only for facts that no code, config or doc can prove:** compliance answers such as Data safety,
|
||||
App Privacy, age rating, export compliance, partial data deletion. Collect ALL of them in ONE batch at the start
|
||||
(`storebound check` and `storebound validate` list them), never one at a time during the run. Reuse answers that
|
||||
are already in the config.
|
||||
4. **Default loop:** plan, then you drive (the API first, your browser tool for consoles without an API), then verify
|
||||
(read it back), then continue. No round trip to the owner in between.
|
||||
5. **Catch rejections offline.** Before a write, `storebound check` and `--dry` must catch what the store would refuse
|
||||
(live-shape fixtures, id and pair checks). A failure belongs in the dry run, not in a 400 at write time; when a
|
||||
store refuses something the dry run passed, fix the check (pitfalls), not just the data.
|
||||
|
||||
Every hour of "please click this" is an hour the owner did not want to spend. If you catch yourself writing "you
|
||||
need to ...", do it instead, unless it is one of the owner steps in point 2.
|
||||
|
||||
## The other rules
|
||||
|
||||
**Read `skills/store-pitfalls/SKILL.md` before any store task.** It lists the mistakes already made in real releases
|
||||
(store lists that lag after a create, dry runs without a plan, taken App Store names, byte limits, ...) and what to do.
|
||||
|
||||
1. **The owner decides public and irreversible steps.** Submitting for review (App Review or Beta App Review),
|
||||
releasing a version, resuming or completing a rollout, canceling a submission, deleting products or listings,
|
||||
accepting agreements, sending review replies, inviting or removing testers, changing prices, starting or stopping
|
||||
a store experiment: explain what will happen and let the owner do it (or run the command only after a clear yes in
|
||||
chat). storebound's MCP server does not offer these at all.
|
||||
2. **Dry run first.** Every write command has `--dry` (MCP: `dry_run`, default true). Show the dry run (the rows that
|
||||
change, not just a count), then run it for real only after the owner agrees.
|
||||
1. **The owner presses only the owner steps** (point 2 of the first rule). Prepare them completely, say what will
|
||||
happen, and let the owner press the button, or run the command only after a clear yes in chat. storebound's MCP
|
||||
server does not offer these at all. Everything else you run yourself.
|
||||
2. **Dry run first, then run it yourself.** Every write command has `--dry` (MCP: `dry_run`, default true). Run the
|
||||
dry run, check and show it (the rows that change, not just a count), then run the real command yourself (`--yes`
|
||||
where it asks for a confirmation) and read the result back. Wait for the owner's yes only before an owner step.
|
||||
3. **Read before you write.** `storebound scan` (offline: rejection risks in the project itself), `storebound check`
|
||||
(offline) and `storebound validate` (read-only, both stores) tell you what is missing and in which order to fix it.
|
||||
4. **Credentials only from the environment, `.storebound/`** in the project (gitignored) **or a credential profile**
|
||||
|
|
@ -19,7 +46,8 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
passwords or tokens in chat, never print them, never write them into the config, docs or commits. The same goes
|
||||
for the App Review demo account (`reviewDemoAccount` in `.storebound/credentials.json`): the owner puts it there.
|
||||
5. **Never answer a compliance question you cannot know.** Export compliance, Data safety, App Privacy, age rating,
|
||||
target audience: ask the owner when the code does not prove the answer. A wrong "no" is worse than a slow "ask".
|
||||
target audience: ask the owner when the code does not prove the answer, all such questions in one batch at the
|
||||
start (first rule, point 3), and write the answers into the config. A wrong "no" is worse than a slow "ask".
|
||||
6. **Pick builds by explicit number.** Use the build number / versionCode you just uploaded, never "the latest".
|
||||
7. **Long uploads run in the background with a log** (`storebound play images > .storebound/images.log 2>&1 &`) and
|
||||
you report the progress lines, not guesses.
|
||||
|
|
@ -31,7 +59,7 @@ These rules apply to every AI tool that uses storebound (skills, MCP server or t
|
|||
10. **Console forms without an API: drive them yourself, agent-first.** `storebound console plan <form> --json` (MCP
|
||||
`console_plan`) gives the start URL, steps, the answer sheet, the buttons you must never press and the verified UI
|
||||
facts. Drive the page with your own browser tool, adapt to what it shows, run long flows as an in-page async loop
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop before the final button (Publish,
|
||||
that writes `window.__log` (one evaluate call times out around 45 s), stop only before the final button (Publish,
|
||||
Submit, Create, a final Save) and tell the owner exactly what to press, then `storebound console verify <form>`.
|
||||
Never sign in, accept an agreement or grant a permission (a service account's app access) for the owner.
|
||||
`storebound console fill` is the optional scripted fast path; it never blocks you.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ fails without the fix.
|
|||
|
||||
| # | date | lesson | guard |
|
||||
|---|---|---|---|
|
||||
| 26 | 2026-10 | An agent using storebound spent hours handing the owner one click, command or answer at a time ("press Next", "download the CSV template", "now run the upload", a compliance question in the middle of a run): skills said "let the owner do it" / "by hand" for navigation, exports and uploads. | The first rule "Do it, don't ask" heads `docs/agents-core.md` (every generated adapter), README and the store-pitfalls skill: the agent does API calls, uploads, builds, exports, console navigation and forms itself; the owner presses only the final public or irreversible buttons and answers the facts no file proves in one batch at the start. `tests/do-it-dont-ask.test.ts` checks the rule is there and fails on skill text that hands navigation, draft saves, exports, uploads or form filling to the owner. |
|
||||
| 25 | 2026-10 | In a non-interactive shell `play build` stopped in Gradle with "SDK location not found" (no `ANDROID_HOME` there, `local.properties` gitignored) although the SDK was in `~/Library/Android/sdk`; `apple upload --no-wait --yes` sent the IPA for over 10 minutes without a line (progress every 10th part only, no per-part or per-call timeout). | `resolveAndroidSdk` (ANDROID_HOME, ANDROID_SDK_ROOT, `sdk.dir` in local.properties, the Android Studio default folder; only folders with platforms/ or platform-tools/) hands the SDK to Gradle in the environment, never writes local.properties, stops before Gradle with the places checked; `doctor` shows it (`cli/lib/tools.ts`, `cli/play/build.ts`, `cli/doctor.ts`). `apple upload` prints the size, a line per part and a 20 s heartbeat (api, altool, processing wait), per-part and per-call timeouts, `--timeout` exits 7 with the resume hint (`sendParts` in `cli/apple/upload.ts`, `cli/lib/progress.ts`; `tests/tools-path.test.ts`, `tests/build-sign.test.ts`, `tests/upload-progress.test.ts`). |
|
||||
| 24 | 2026-10 | `flow run release --apply --yes` ran `apple upload --no-wait`, which printed "not a terminal: re-run with --yes to confirm" and declined, yet the flow logged "4/13 upload: ok" and went on to `apple testflight wait` for a build that was never uploaded: a declined confirmation exited 0, and the flow's `--yes` never reached the steps. | `confirm()` (`cli/lib/ctx.ts`): every decline (answered no, not a terminal without `--yes`, under serve) prints `declined: <reason>` and exits 3 (`DECLINED_EXIT`). `flow run` reports "step N declined: <reason>" (status `declined`) and stops; `--apply --yes` adds `--yes` to write steps only (`planStep`, `declinedReason`; `tests/flow.test.ts`). |
|
||||
| 23 | 2026-10 | Capacitor: native build ships old web assets. `flow run release --apply` went straight into `apple build` (xcodebuild archive) with `ios/App/App/public` and `android/app/src/main/assets/public` 3.5 hours older than the latest source commit: the native projects hold the copy `npx cap sync` made last, and nothing ran the web build + cap sync first, so the old game would have shipped. | New `build.prebuild` (per store `apple.prebuild` / `play.prebuild`): `apple build` / `play build` run it first (printed, streamed, nonzero exit stops; `--dry` only prints; `--no-prebuild`; once per `flow run` through `STOREBOUND_PREBUILD_DONE`). After it, a Capacitor project's copied `public/index.html` must be newer than the last commit outside ios/ android/ node_modules/ store/ .storebound/ and `<webDir>/index.html`, else the build stops ("web assets are older than the source ..."; `--allow-stale-web` overrides). `check` warns when stale without a prebuild; build output and dry plan show the bundle's sha256 + mtime. Monorepo (`apps/native` with its own capacitor.config.ts, android/, ios/; `play build` failed with "no Gradle project ... in android or ."): the one Capacitor project one or two levels down is found and named, several ask for `play.build.dir` / `apple.build.*` (`cli/lib/web-assets.ts`, `tests/web-assets.test.ts`). |
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ other platforms' UI. Play promo video: YouTube URL, public or unlisted, ads off,
|
|||
## Steps
|
||||
1. **Hands-free footage.** Give the game an autoplay / attract mode switch, or the app a scripted demo of its main
|
||||
flow on sample data (URL param, launch argument or intent extra), plus the screenshot switches (language, fixed
|
||||
seed or demo data, no ads). Otherwise record the screen yourself and use `--source folder`.
|
||||
seed or demo data, no ads). Otherwise record the screen (simulator, emulator or browser recording you start) and use `--source folder`.
|
||||
2. **Clips.** `shots.video.record.clips`: per clip `seconds` (1-60) and `path` (web, after `shots.capture.baseUrl`),
|
||||
or `url` / `args` / `extras` (simulator / emulator), `waitFor`, `delayMs`. The source and its settings come from
|
||||
`shots.capture` (or `record.source`). `storebound shots record --dry` shows the plan, then
|
||||
|
|
@ -48,7 +48,9 @@ other platforms' UI. Play promo video: YouTube URL, public or unlisted, ads off,
|
|||
the page with their poster). Watch at least one language end to end.
|
||||
5. **Upload.** App Store: `storebound apple previews --dry`, then `storebound apple previews` (editable version,
|
||||
MD5-idempotent, poster frame from `--poster` / `shots.video.poster`, files checked before anything is sent).
|
||||
Play: upload `preview/youtube/01.mp4` to YouTube yourself, set `play.video`, run `storebound play listing`
|
||||
Play: the video must be on YouTube. Publishing on the owner's channel is public, so ask for it in the start batch
|
||||
(or for an existing video URL); upload it with your browser tool once the owner said yes, set `play.video`, run
|
||||
`storebound play listing`
|
||||
(the listing PUT replaces the whole listing: without `play.video` a video set in Play Console is cleared).
|
||||
|
||||
## From an AI tool (MCP)
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ or `bun <toolchain>/cli/index.ts`; agents can also use the `storebound mcp` tool
|
|||
Config: `storebound.config.ts`; credentials: `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_P8` (env or
|
||||
`.storebound/credentials.json`, gitignored). All commands are idempotent and have `--dry`. Run `storebound check` first.
|
||||
|
||||
**Ask the owner before submitting for review, releasing, or canceling a submission.** The final "Submit for Review"
|
||||
of a first version is the owner's click. Shared agent rules: `docs/agents-core.md` of the toolchain.
|
||||
**Do it, don't ask** (first rule in AGENTS.md / `docs/agents-core.md` of the toolchain): you run every step below
|
||||
yourself, API steps with storebound and UI steps in App Store Connect with your browser tool, and verify each. The
|
||||
owner only presses Submit for Review, Release, App Privacy Publish, cancels a submission or accepts agreements, and
|
||||
answers the compliance facts no file proves, all in one batch at the start.
|
||||
|
||||
## Steps (API = storebound, UI = App Store Connect / Xcode by hand)
|
||||
## Steps (API = storebound, UI = App Store Connect, driven by you with your browser tool; Local = this machine)
|
||||
|
||||
1. **UI · API key.** App Store Connect > Users and Access > Integrations > App Store Connect API > Team Keys > +
|
||||
(Admin or App Manager). Download `AuthKey_<KEYID>.p8` once, keep it in `~/.appstoreconnect/private_keys/`, note the
|
||||
|
|
@ -49,21 +51,23 @@ of a first version is the owner's click. Shared agent rules: `docs/agents-core.m
|
|||
description / keywords / promo / URLs). Run it with `--dry` first and show the owner the plan: the version decision
|
||||
(keep, update the editable version's string, create, or refuse with the reason), the build, and per locale create /
|
||||
update with old -> new per field. Locales still marked `status=draft` / `status=translate` are skipped until
|
||||
`listing reviewed` (`--include-drafts` only when the owner says so). The real run asks in a terminal and applies
|
||||
exactly that plan. Then `storebound apple release --phased on`: manual release + phased
|
||||
`listing reviewed` (`--include-drafts` only when the owner says so). Then run it yourself with `--yes`: it
|
||||
applies exactly that plan. Then `storebound apple release --phased on`: manual release + phased
|
||||
release is the default for every version (`release-management`).
|
||||
8. **API · Screenshots.** `store-screenshots` skill, then
|
||||
`storebound apple screenshots > .storebound/asc-shots.log 2>&1 &` (6.9" + 6.5" per locale, MD5-idempotent).
|
||||
9. **API · App info.** `storebound apple appinfo` (`--dry` first: old -> new per field): categories, age rating declaration, content rights, Free price,
|
||||
all territories. The **first** availability record of a new app may be refused by the public API (an error on
|
||||
POST /v2/appAvailabilities); then set it once in App Store Connect > Pricing and Availability and re-run (later runs only read it).
|
||||
POST /v2/appAvailabilities); then set it once in App Store Connect > Pricing and Availability with your browser
|
||||
tool and re-run (later runs only read it).
|
||||
10. **API · Review details.** `storebound apple review-details` (contact from `.storebound/credentials.json`
|
||||
`reviewContact`, or `--contact-from <Apple ID of another app of the team>`; notes from the config). Apps behind a
|
||||
sign-in: the demo account from `.storebound/` (`review-access` skill). Apps with accounts: in-app deletion
|
||||
(`account-deletion` skill).
|
||||
11. **API + UI · In-app purchases and subscriptions.** `store-iap-setup` and `store-subscriptions` skills. First
|
||||
IAPs and subscriptions go to review **with** this version.
|
||||
12. **UI · App Privacy.** `store-declarations` skill (nutrition labels), then **Publish**.
|
||||
12. **UI · App Privacy.** `store-declarations` skill (nutrition labels; you fill and save them), then the owner
|
||||
presses **Publish**.
|
||||
13. **Preflight.** `storebound validate --apple` until it shows no blocker (`store-preflight`).
|
||||
14. **UI · Submit.** Version page > Add for Review (with the IAPs in the same draft submission) > Submit for Review
|
||||
(owner). Release type MANUAL means the owner presses "Release" after approval.
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ true; never use competitor or other apps' or games' names, "best / #1", or unrel
|
|||
owner's step.
|
||||
- A subtitle change ships with a version: change one thing, then compare with `analytics compare`.
|
||||
- Google Play store listing experiments (short / full description, icon, feature graphic, screenshots) have no API:
|
||||
storebound prepares the text and renders; the owner sets the experiment up in Play Console.
|
||||
storebound prepares the text and renders, you set the experiment up in Play Console with your browser tool, and
|
||||
the owner presses the button that starts it.
|
||||
|
||||
## Where the numbers come from (say it to the owner)
|
||||
| number | source | is | is not |
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ description: Fill App Store Connect and Google Play Console forms that have no A
|
|||
|
||||
CLI: `storebound` (or `bunx storebound` in a project that has it, or `bun <toolchain>/cli/index.ts`).
|
||||
|
||||
**Do it, don't ask** (first rule in AGENTS.md / `docs/agents-core.md`): you open the console, navigate, fill the form,
|
||||
save drafts and verify; the owner only signs in once and presses the final button. Ask the owner's `ask-owner`
|
||||
answers in one batch before you start, never one at a time on the page.
|
||||
|
||||
**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
|
||||
|
|
@ -27,7 +31,8 @@ the UI shows. This is the primary mode.
|
|||
- `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
|
||||
2. Collect the `ask-owner` answers of every form you will fill in ONE question to the owner before you start (AGENTS.md
|
||||
rule 5) and write them into the config, so the plan has them. 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
|
||||
|
|
@ -68,15 +73,15 @@ the UI shows. This is the primary mode.
|
|||
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).
|
||||
later. Granting them is the owner's (a permission grant; auto mode blocks it too): give the exact path together
|
||||
with the Create app button, Users and permissions > the service account > Add app > the new app > Admin (or the
|
||||
minimal set the plan lists) > Apply > Save changes; then run `storebound apps check --store play` yourself.
|
||||
|
||||
## 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).
|
||||
fix. It is not available over MCP: run it from your shell (or the owner uses the desktop app).
|
||||
|
||||
## Forms
|
||||
|
||||
|
|
@ -93,7 +98,7 @@ fix. It is not available over MCP (the owner runs it in a terminal or the deskto
|
|||
|
||||
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.
|
||||
2. For each `[check]` line, ask the owner (AGENTS.md rule 5: never guess a compliance answer). If they want it filled
|
||||
2. Ask the owner about every `[check]` line in one batch before the run (AGENTS.md rule 5: never guess a compliance answer). If they want it filled
|
||||
next time, add it to the config, for example:
|
||||
```ts
|
||||
console: {
|
||||
|
|
@ -103,8 +108,8 @@ fix. It is not available over MCP (the owner runs it in a terminal or the deskto
|
|||
},
|
||||
```
|
||||
Age rating answers live in `apple.info.ageRating` (also `socialMedia`, `socialMediaAgeRestricted`).
|
||||
3. The owner runs `storebound console fill <form>` in a terminal (or presses the button in the desktop app). The
|
||||
first log line says which browser it uses:
|
||||
3. Run `storebound console fill <form>` yourself from a shell (the desktop app has a button for it too). The first
|
||||
log line says which browser it uses:
|
||||
- **profile** (the default): storebound's own profile (`~/.storebound/console-profile/<store>`, or `--profile <dir>`
|
||||
/ `STOREBOUND_CONSOLE_PROFILE`; one per store, not per account: every studio shares the one login). Nothing is
|
||||
read or copied from the owner's own Chrome. storebound starts Chrome itself as a normal window (its own
|
||||
|
|
@ -158,8 +163,9 @@ fix. It is not available over MCP (the owner runs it in a terminal or the deskto
|
|||
Save, Submit, Publish, Create, Send, Next or the Turkish equivalents; only a LINK named exactly Start / Manage /
|
||||
Başla / Yönet is let through. If a step is not found in time, or two apps match (they are listed: set
|
||||
`apple.appId` / `play.packageName`), storebound says which step failed, prints what to click, and keeps watching:
|
||||
a sign-in that finishes restarts navigation at step 1; when the owner moves on by hand (the + button, the New App
|
||||
item, the app in the list appear) it continues from that step; when the owner opens the form it fills it. Watching
|
||||
a sign-in that finishes restarts navigation at step 1; when the page moves on (you click the step with your
|
||||
browser tool: the + button, the New App item, the app in the list appear) it continues from that step; when the
|
||||
form is open it fills it. Watching
|
||||
ends when the window is closed. When the form appears storebound fills the certain answers, outlines every
|
||||
unproven or unfillable field with a "storebound: check this" label, and lists them in the terminal.
|
||||
5. **One login, many developer accounts or teams.** storebound never asks for a second sign-in; it finds the
|
||||
|
|
@ -204,7 +210,8 @@ fix. It is not available over MCP (the owner runs it in a terminal or the deskto
|
|||
step: attach that folder to a bug report after looking at screen.jpg (labels only; no values, cookies or tokens;
|
||||
emails, phone numbers and the account area are replaced).
|
||||
9. If a field cannot be found or matches twice (for more than a moment: a page that is still loading does not count), the console UI changed: storebound stops filling and prints the
|
||||
step-by-step list ("label: answer") for the owner to copy. That is the expected safe behavior, not an error.
|
||||
step-by-step list ("label: answer"). That is the expected safe behavior, not an error: finish that part yourself
|
||||
with your browser tool (agent-first mode above), not by handing the list to the owner.
|
||||
|
||||
## Play Create app (`play-app-record`)
|
||||
|
||||
|
|
@ -225,7 +232,8 @@ fix. It is not available over MCP (the owner runs it in a terminal or the deskto
|
|||
"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).
|
||||
- After Create app: the owner grants the service account access to the new app (a permission grant; see "Verified UI
|
||||
facts" above), then you run `storebound apps check --store play`.
|
||||
|
||||
## What storebound clicks, and what stays with the owner
|
||||
|
||||
|
|
@ -242,8 +250,8 @@ content", "Create and set up your 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 |
|
||||
|
||||
Mid-way storebound stops only for an uncertain answer (see 6). It never asks the owner to click a navigation button
|
||||
unless the console page changed so that storebound cannot find it (then it says so).
|
||||
Mid-way storebound stops only for an uncertain answer (see 6). A navigation button is never the owner's: when the
|
||||
console page changed so that storebound cannot find it, it says so and you click it with your browser tool.
|
||||
|
||||
## The owner decides
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ or `bun <toolchain>/cli/index.ts`; agents can also use the `storebound mcp` tool
|
|||
It reads `storebound.config.ts` in the project (create with `storebound init`) and credentials from env or
|
||||
`.storebound/credentials.json` (gitignored). Every write command has `--dry`. Run `storebound check` first.
|
||||
|
||||
**Ask the owner before anything public or irreversible**: production releases, "Send for review", publishing,
|
||||
deleting products. Sending a first release for review is the owner's action in the Console, not yours.
|
||||
**Do it, don't ask** (first rule in AGENTS.md / `docs/agents-core.md`): you run every step below yourself, API steps
|
||||
with storebound and UI steps in Play Console with your browser tool, and verify each. The owner only presses the
|
||||
public or irreversible buttons (Send changes for review, production release or rollout, agreements, deleting
|
||||
products) and answers the compliance facts no file proves, all in one batch at the start.
|
||||
|
||||
## Steps (API = storebound does it, UI = Play Console by hand)
|
||||
## Steps (API = storebound, UI = Play Console, driven by you with your browser tool)
|
||||
|
||||
1. **UI · Create the app.** `storebound console plan play-app-record` (then drive the form with your browser tool,
|
||||
or the scripted `storebound console fill play-app-record`). The form is
|
||||
|
|
@ -25,10 +27,11 @@ deleting products. Sending a first release for review is the owner's action in t
|
|||
`/console/u/0/developers/<developerId>/app/<appId>/app-dashboard`: put that app id in `play.appId` (the App
|
||||
content forms deep-link from it).
|
||||
**Owner step after every Create app:** 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 at least: view app
|
||||
information, manage store presence, release to testing tracks, manage testing tracks, manage production releases,
|
||||
manage policy declarations, manage orders and subscriptions) > Apply > Save changes. Never do this yourself: it is
|
||||
a permission grant (agents in auto mode are blocked from it too). Then `storebound apps check --store play`.
|
||||
Granting them is the owner's (a permission grant; agents in auto mode are blocked from it too): give the exact
|
||||
path in the same message as the Create app button, Users and permissions > the service account > Add app > the new
|
||||
app > Admin (or at least: view app information, manage store presence, release to testing tracks, manage testing
|
||||
tracks, manage production releases, manage policy declarations, manage orders and subscriptions) > Apply > Save
|
||||
changes. Then run `storebound apps check --store play` yourself.
|
||||
2. **UI · API access.** Google Cloud project (any) > enable "Google Play Android Developer API" > create a service
|
||||
account > JSON key (keep it outside the repo). Play Console > Users and permissions > Invite new users > the
|
||||
service account email > app permissions: view app information, manage store presence, release to testing tracks,
|
||||
|
|
@ -52,7 +55,7 @@ deleting products. Sending a first release for review is the owner's action in t
|
|||
6. **API · Listing text.** Fill `store/listing.md` (one section per language), then `storebound play listing`.
|
||||
It also sets contact email + website (website = the domain serving app-ads.txt). Run `--dry` first and show the
|
||||
owner the plan (details and per language old -> new per field; draft languages skipped until `listing reviewed`,
|
||||
`--include-drafts` only on the owner's word); the real run asks in a terminal and PUTs only what changes.
|
||||
`--include-drafts` only on the owner's word); then run it yourself with `--yes`: it PUTs only what changes.
|
||||
7. **API · Graphics.** Render (`store-screenshots` skill), `storebound shots jpeg`, then
|
||||
`storebound play images > .storebound/play-images.log 2>&1 &` and follow the log (it is slow: one edit per language).
|
||||
Required: the 512 x 512 icon, the 1024 x 500 feature graphic and at least 2 phone screenshots (Play Console Help
|
||||
|
|
@ -68,7 +71,8 @@ deleting products. Sending a first release for review is the owner's action in t
|
|||
with the demo account (`review-access`); with accounts: the delete-account URL (`account-deletion`); subscriptions:
|
||||
`storebound play subscriptions` (`store-subscriptions`).
|
||||
11. **UI · Store settings.** Category + tags, contact details.
|
||||
12. **API + UI · Production.** `storebound play release --version-code N --production draft`, then in the Console:
|
||||
12. **API + UI · Production.** `storebound play release --version-code N --production draft`, then in the Console
|
||||
(you, with your browser tool):
|
||||
Production > Countries/regions > Add countries > select all > Save; Production > the draft release > Edit >
|
||||
Next > Save; Publishing overview > **Send changes for review** (owner).
|
||||
13. **Verify.** `storebound validate --play` (no blockers), `storebound play status` (tracks, listings, products), Console dashboard has no open tasks,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ description: Repo-local workflows for a mobile app or game - named multi-step fl
|
|||
# Release flows
|
||||
|
||||
CLI: `storebound flow list | validate | run <name> [NAME=value ...] [--dry | --apply] [--from <step> | --resume]`.
|
||||
MCP: `flow_list`, `flow_run` (always the safe mode: writes as dry runs; `--apply` is a terminal command the owner runs).
|
||||
MCP: `flow_list`, `flow_run` (always the safe mode: writes as dry runs; `--apply` is a CLI command: run it from your
|
||||
shell after the dry run).
|
||||
|
||||
## Where flows live
|
||||
- `store/workflows/<name>.yml` (one flow per file, named after the file; `.yaml`, `.json` and `.ts` work too), or
|
||||
|
|
@ -45,11 +46,11 @@ once (the second build step prints "prebuild skipped (already ran in this flow r
|
|||
run for real; **every write step runs with `--dry`**; wait steps check once; shell steps are skipped. Nothing
|
||||
changes. Show this output to the owner.
|
||||
- `--dry`: the plan only, nothing runs.
|
||||
- `--apply`: writes and shell steps run for real, **only after the owner agreed in chat**; each write command still
|
||||
asks its own confirmation in the terminal. Never add `--yes` to a step (flow validate refuses it).
|
||||
- `--apply --yes`: the owner's approval of every write step of this run (they get `--yes`; reads, waits and owner
|
||||
steps do not). Only when the owner said so in chat for this run, e.g. a background run with a log where no terminal
|
||||
can answer. Without `--yes` and without a terminal, a confirming command declines: the flow stops there with
|
||||
- `--apply`: writes and shell steps run for real; each write command still asks its own confirmation in the
|
||||
terminal. Never add `--yes` to a step (flow validate refuses it).
|
||||
- `--apply --yes`: how you run it after showing the dry run (do it, don't ask: AGENTS.md first rule): every write
|
||||
step gets `--yes`; reads, waits and owner steps do not, so nothing owner-only runs. When the dry run shows a live price change
|
||||
(`play products`, `apple subscriptions` on an existing product), get the owner's yes for it first. Without `--yes` and without a terminal, a confirming command declines: the flow stops there with
|
||||
"step N declined: not a terminal and no --yes ...", never "ok" (status `declined` in `--json` and the state file).
|
||||
- Owner steps never run in any mode: submit, release, phased release, rollout, sending review replies, price
|
||||
imports, inviting testers, Beta App Review, starting experiments, offer codes (AGENTS.md rule 1). They print as
|
||||
|
|
|
|||
|
|
@ -71,4 +71,4 @@ Before pushing local texts over a console edit, pull the live ones and read the
|
|||
shared by several codes is only changed when the store has the same text for all of them.
|
||||
- `storebound catalog pull [--write]`: IAP and subscription titles / descriptions (Play: benefits) against the config.
|
||||
`storebound.config.ts` is never rewritten: `--write` saves `.storebound/pull/catalog.json` as a proposal; merge the
|
||||
listings by hand or with your agent, then `storebound check`.
|
||||
listings into the config yourself (the agent), then `storebound check`.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ keyword repetition, other apps), interstitials at launch, payments outside Play
|
|||
a rejection, run it too: the same cause often hides elsewhere. A finding the owner decided is fine goes
|
||||
into `scan.ignore` with the reason (never silence one yourself).
|
||||
|
||||
Checked at review, not by scan (look at these by hand): crashes and hangs on the reviewer's device (2.1; `store-health`),
|
||||
Checked at review, not by scan (check these yourself in the app and the listing): crashes and hangs on the reviewer's device (2.1; `store-health`),
|
||||
links that are dead at review time (`storebound validate` checks the configured URLs), screenshots and description
|
||||
that do not match the app (2.3, `store-screenshots`), poor or unfinished UI (4.0), "too simple" and spam / template
|
||||
apps (4.2, 4.3; `portfolio-originality`), IAPs that fail in the sandbox (2.1(b), `store-iap-setup`), privacy policy
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ description: Answer the store compliance forms for a mobile app or game - Google
|
|||
|
||||
# Store declarations
|
||||
|
||||
**Do it, don't ask** (first rule in AGENTS.md): you fill these forms yourself (API, or the console with your browser
|
||||
tool from `storebound console plan`). Ask the owner only the answers no code or config proves, all in one batch at
|
||||
the start, and save them in the config; the owner presses only App Privacy Publish and the final Submit / Save of a
|
||||
console questionnaire.
|
||||
|
||||
`storebound scan` proposes the Data safety and App Privacy answers from the detected SDKs and code (each item "detected (file:line)" or "ask owner") as a diff against `dataSafety` / `appPrivacy`; `--write` adds only the detected ones after the owner agrees.
|
||||
|
||||
Templates: `store/declarations.md` (Play App content + IARC answers), `store/app-privacy.md` (Apple labels), both
|
||||
|
|
@ -21,12 +26,14 @@ CLI: `storebound` (or `bunx storebound` in a project that has it, or `bun <toolc
|
|||
Play cannot read the form back: storebound keeps the hash of the last upload in `.storebound/data-safety.sha256`
|
||||
and skips an unchanged CSV. After a hand edit in Play Console, `--force` sends the config's answers again.
|
||||
Then check the summary in Play Console > Policy and programs > App content > Data safety.
|
||||
3. **Play App content (UI).** Policy and programs > App content, each card with `store/declarations.md`:
|
||||
3. **Play App content (UI, you drive it).** Policy and programs > App content, each card with `store/declarations.md`
|
||||
(`storebound console plan play-content-rating` / `play-target-audience` for the forms it knows):
|
||||
privacy policy, app access, ads, content rating (IARC questionnaire), target audience and content, news, COVID-19,
|
||||
data safety, government apps, financial features, health, advertising ID.
|
||||
4. **Apple age rating (API).** `storebound apple appinfo` (all NONE except your overrides, e.g. `advertising: true`).
|
||||
5. **Apple App Privacy (UI only).** App Store Connect > the app > App Privacy > Get Started / Edit, from
|
||||
`store/app-privacy.md`; per data type: purposes > linked to identity > used for tracking. Then **Publish**.
|
||||
5. **Apple App Privacy (UI only, you drive it: `storebound console plan apple-app-privacy`).** App Store Connect >
|
||||
the app > App Privacy > Get Started / Edit, from `store/app-privacy.md`; per data type: purposes > linked to
|
||||
identity > used for tracking, Save. Then the owner presses **Publish**.
|
||||
- Purposes follow Apple's definitions (developer.apple.com/app-store/app-privacy-details/), one per Play purpose:
|
||||
Play `advertising` (ads from an ad SDK) is **Third-Party Advertising only**, never also Developer's Advertising
|
||||
or Marketing (that one is first-party ads or marketing to your own users: the owner's answer); `analytics` is
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: store-pitfalls
|
||||
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins, duplicates from retries, re-runs and parallel runs, App Store search ranks that are only a trend, Play without a search API, Play's Create app form (no API, opener and submit share a name, Free is final), App Privacy purposes over-mapped (Play advertising is Third-Party Advertising only), an unknown console page, a signed-in console read as a sign-in page (Google account widget frames), console forms driven agent-first, stale Capacitor web assets, a declined flow step logged ok. Read it before any store task, and when a store command does something you did not expect.
|
||||
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - first: do the work, don't ask the owner for every step; store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins, duplicates from retries and re-runs, search ranks that are only a trend, no Play search API, Play's Create app form (no API, opener and submit share a name, Free is final), App Privacy purposes over-mapped (Play advertising is Third-Party Advertising only), an unknown console page, a signed-in console read as a sign-in page, console forms driven agent-first, stale Capacitor web assets, a declined flow step logged ok. Read it before any store task, and when a store command does something you did not expect.
|
||||
---
|
||||
|
||||
# Store pitfalls
|
||||
|
|
@ -8,6 +8,14 @@ description: Known pitfalls with App Store Connect, Google Play and storebound i
|
|||
Each entry: **symptom** → cause → what to do → what guards it now. The full changelog of lessons with dates is
|
||||
`docs/pitfalls.md` in the storebound repository. When you hit a new one, tell the owner and add it there (and here).
|
||||
|
||||
## First: do it, don't ask (the costliest pitfall)
|
||||
You and storebound do everything: API calls, uploads, builds, CSV / template exports, every console navigation
|
||||
(open, Get Started, Edit, Next, Continue, Save draft), console forms, verification. Never hand the owner "run this" or
|
||||
"click X". The owner presses only the final public or irreversible buttons (Submit for review, release or a
|
||||
production rollout, App Privacy Publish, legal agreements; deleting store data, live prices, review replies,
|
||||
testers) and answers, in ONE batch at the start, only the facts no file proves (compliance answers that `check` /
|
||||
`validate` list). Loop: plan, drive, verify, continue. Full rule: `docs/agents-core.md` (AGENTS.md); lesson 26.
|
||||
|
||||
## 1. A product you just created is "not there"
|
||||
- **Symptom:** `apple iap-review` uploads nothing for a product `apple iap` created a minute ago; a list looks short.
|
||||
- **Cause:** App Store Connect's `/inAppPurchasesV2` list (and Play's product list) can lag for a short while after a
|
||||
|
|
@ -135,7 +143,7 @@ Each entry: **symptom** → cause → what to do → what guards it now. The ful
|
|||
- **Cause:** the console showed a page storebound does not recognise (a changed layout, a new question): no field it
|
||||
can fill and no button it may click.
|
||||
- **Do:** read the warning: it names the page ("the page after "Next""), its buttons, and where the debug dump is.
|
||||
Do that part by hand (the manual steps follow), or stop. To report it, re-run with `--debug-dump` and attach the
|
||||
Drive that part yourself with your browser tool from `storebound console plan <form>` (agent-first), then go on. To report it, re-run with `--debug-dump` and attach the
|
||||
folder `.storebound/console-debug/<form>-<time>/` after the owner looked at `screen.jpg` (the screenshot shows what
|
||||
the window showed). `page.json` / `page.html` hold labels and structure only: no values, cookies or tokens; emails,
|
||||
phone numbers and the account area are replaced.
|
||||
|
|
@ -291,8 +299,8 @@ that fails without the fix (see CONTRIBUTING.md).
|
|||
`apple testflight wait` for a build that was never uploaded.
|
||||
- **Cause:** a declined confirmation (`confirm()` in `cli/lib/ctx.ts`) returned from the command with exit 0, and
|
||||
`flow run --yes` was not passed on to the steps, so a run without a terminal could never confirm.
|
||||
- **Do:** read a step's output, not only its status. For a run without a terminal the owner can approve the writes
|
||||
with `flow run <name> --apply --yes` (only on their word, per run); otherwise run the flow in a terminal.
|
||||
- **Do:** read a step's output, not only its status. After showing the dry run, run the writes yourself with
|
||||
`flow run <name> --apply --yes` (owner steps never run in a flow, they print as "YOUR CLICK").
|
||||
- **Guard:** every declined or unanswerable confirmation prints `declined: <reason>` and exits 3 (`DECLINED_EXIT`);
|
||||
`flow run` stops with "step N declined: <reason>" (status `declined`, never `ok`) and adds `--yes` to write steps
|
||||
only with `--apply --yes` (`planStep` in `cli/lib/flow.ts`, `declinedReason` in `cli/flow.ts`).
|
||||
|
|
@ -315,3 +323,20 @@ that fails without the fix (see CONTRIBUTING.md).
|
|||
`sendParts` in `cli/apple/upload.ts`, `cli/lib/progress.ts` (injectable heartbeat), `waitForBuild` in
|
||||
`cli/apple/testflight.ts`, a 2-minute limit per App Store Connect call (`ASC_REQUEST_TIMEOUT_MS`);
|
||||
`tests/tools-path.test.ts`, `tests/build-sign.test.ts`, `tests/upload-progress.test.ts`.
|
||||
|
||||
## 26. Asking the owner for every step
|
||||
- **Symptom:** an agent using storebound spent hours handing the owner one click, one command or one answer at a
|
||||
time: "open App content", "press Next", "download the CSV template", "now run the upload", "what is your
|
||||
answer for X?" in the middle of a run.
|
||||
- **Cause:** skills and rules said "let the owner do it" and "by hand" for navigation, draft saves, exports and
|
||||
uploads, and compliance questions were asked when the run reached them, not at the start.
|
||||
- **Do:** follow the first rule (top of this file, `docs/agents-core.md`): do every API call, upload, build, export,
|
||||
console navigation and form yourself, verify by reading back, go on. Collect every fact no file proves in one batch
|
||||
at the start (`storebound check` / `validate` list them) and save the answers in the config. Stop only for the
|
||||
owner steps (Submit for review, release / production rollout, App Privacy Publish, legal agreements, deleting store
|
||||
data, live prices, review replies, testers), prepared with the dry run shown. Make `check` / `--dry` catch store
|
||||
refusals so they never surface as a 400 mid-run.
|
||||
- **Guard:** the rule is the first section of `docs/agents-core.md` and so of every generated adapter (AGENTS.md,
|
||||
GEMINI.md, Copilot and Cursor rules), of README and of this skill; `tests/do-it-dont-ask.test.ts` checks that and
|
||||
fails when a skill or the rules hand navigation, draft saves, exports, uploads or form filling to the owner
|
||||
(navigation "by hand", uploads or exports left to the owner, asking the owner to click through a form).
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ Each line: number, level (`BLOCKER`, `warn`, `ok`), store, message, and a `fix:`
|
|||
Vitals need the Play Developer Reporting API enabled for the service account; without it `validate` only notes
|
||||
"vitals not readable". `--no-health` skips these checks.
|
||||
|
||||
## What validate cannot see (UI-only, check by hand)
|
||||
## What validate cannot see (UI-only: check them yourself in the console with your browser tool)
|
||||
App Privacy labels published, Play App content declarations (ads, target audience, content rating, advertising ID,
|
||||
App access with the demo account), in-app account deletion working, first subscriptions added to the version,
|
||||
agreements / tax / banking, countries for production on Play. (TestFlight groups and testers: `storebound apple
|
||||
testflight status`.) Tell the owner which are still open.
|
||||
testflight status`.) Fix what you can; tell the owner only what is an owner step (agreements, tax, banking).
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@ images there), so only do that after a test has a winner. What the stores offer,
|
|||
- **Google Play store listing experiments** (Play Console > Grow users > Store listing experiments): up to 2 variants
|
||||
against the current listing; one default-graphics experiment or up to 5 localized experiments at a time; icon,
|
||||
feature graphic, screenshots (+ descriptions for localized ones); stops automatically after 6 months. Console only:
|
||||
the Play Developer API has no experiments endpoint, so storebound renders and checks the variant images and you
|
||||
upload them in the experiment form yourself.
|
||||
the Play Developer API has no experiments endpoint, so storebound renders and checks the variant images and the
|
||||
agent uploads them in the experiment form with its browser tool; starting the experiment is the owner's button.
|
||||
https://support.google.com/googleplay/android-developer/answer/6227309
|
||||
- **App Store Product Page Optimization** (App Store Connect > your app > Product Page Optimization): up to 3
|
||||
treatments against the original, one test at a time, up to 90 days; icon, screenshots and app previews, localized
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ offers, offerCodes, reviewScreenshot, basePlanId, gracePeriod, platforms }] }]`,
|
|||
1. Prerequisites: Apple Paid Applications agreement, banking and tax; Play payments profile and a build with the
|
||||
billing library on a track.
|
||||
2. `storebound check` (limits: Apple name 30 / description 45; Play description 200, up to 4 benefits).
|
||||
3. `storebound apple subscriptions --dry` and `storebound play subscriptions --dry`; read the plan with the owner; then
|
||||
run them in a terminal (they ask). Through MCP (no terminal) they only create what is new; price changes of
|
||||
existing subscriptions wait for the owner.
|
||||
3. `storebound apple subscriptions --dry` and `storebound play subscriptions --dry`; show the plan, then run them
|
||||
yourself (`--yes`). A price change of an existing subscription is a live price: get the owner's yes for it first.
|
||||
Through MCP (no terminal) they only create what is new; price changes of existing subscriptions wait for the owner.
|
||||
4. Review screenshot of the paywall per subscription (`reviewScreenshot`), uploaded by `apple subscriptions`.
|
||||
5. **First subscriptions go with an app version** (and a new group with at least one of its subscriptions):
|
||||
`storebound apple iap-submit --with-version --dry` plans one review submission with the app version, the
|
||||
|
|
|
|||
69
tests/do-it-dont-ask.test.ts
Normal file
69
tests/do-it-dont-ask.test.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// Pitfall 26: an agent spent hours handing the owner one click, command or answer at a time. The first rule
|
||||
// "Do it, don't ask" must head the agent rules (and so every generated adapter), README and the pitfalls skill, and
|
||||
// no skill or rule text may hand navigation, draft saves, exports, uploads or form filling to the owner.
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const root = join(import.meta.dir, '..');
|
||||
const read = (rel: string) => readFileSync(join(root, rel), 'utf8');
|
||||
const RULE = "do it, don't ask";
|
||||
|
||||
describe("first rule: do it, don't ask", () => {
|
||||
test('is the first section of docs/agents-core.md, above the numbered rules', () => {
|
||||
const core = read('docs/agents-core.md');
|
||||
const firstHeading = /^## (.*)$/m.exec(core)?.[1] ?? '';
|
||||
expect(firstHeading.toLowerCase()).toContain(RULE);
|
||||
expect(core.indexOf('## First rule')).toBeLessThan(core.indexOf('1. **The owner presses only the owner steps**'));
|
||||
for (const owner of ['Submit for review', 'App Privacy Publish', 'legal', 'live prices', 'review replies', 'testers'])
|
||||
expect(core).toContain(owner);
|
||||
expect(core).toMatch(/ONE batch at the start/);
|
||||
});
|
||||
|
||||
test('reaches every generated adapter, README and the lead of store-pitfalls', () => {
|
||||
for (const f of ['AGENTS.md', 'GEMINI.md', '.github/copilot-instructions.md', '.cursor/rules/storebound.mdc'])
|
||||
expect(read(f).toLowerCase()).toContain(RULE);
|
||||
const readme = read('README.md');
|
||||
const at = readme.indexOf('## How agents use storebound');
|
||||
expect(at).toBeGreaterThan(0);
|
||||
expect(readme.slice(0, at).split('\n## ').length).toBe(1); // the first section of README
|
||||
const pit = read('skills/store-pitfalls/SKILL.md');
|
||||
expect(/^## (.*)$/m.exec(pit)?.[1]?.toLowerCase()).toContain(RULE);
|
||||
for (const s of ['console-autofill', 'play-first-release', 'appstore-first-release', 'store-declarations'])
|
||||
expect(read(`skills/${s}/SKILL.md`).toLowerCase()).toContain(RULE);
|
||||
});
|
||||
|
||||
// Phrases that hand agent work (navigation, draft saves, exports, uploads, form filling, commands) to the owner.
|
||||
const HANDOFF: RegExp[] = [
|
||||
/\bUI = [^)\n]*by hand/i,
|
||||
/\bask the owner to (click|press next|open|navigate|download|upload|export|fill|save|copy|run)\b/i,
|
||||
/\b(have|let) the owner (click|open|navigate|download|upload|export|fill|save|copy|run)\b/i,
|
||||
/\bthe owner (clicks|opens|navigates|downloads|uploads|exports|fills|copies|pastes)\b/i,
|
||||
/\b(click|download|upload|export|navigate)\b[^.\n]{0,60}\byourself\b/i,
|
||||
/\b(do|fill|finish) (that|this) (part )?by hand\b/i,
|
||||
/\bfor the owner to copy\b/i,
|
||||
];
|
||||
const files = ['docs/agents-core.md', 'README.md',
|
||||
...readdirSync(join(root, 'skills')).map(n => `skills/${n}/SKILL.md`).filter(f => { try { read(f); return true; } catch { return false; } })];
|
||||
|
||||
test('no skill or rule hands navigation, exports, uploads or forms to the owner', () => {
|
||||
const hits: string[] = [];
|
||||
for (const f of files) {
|
||||
read(f).split('\n').forEach((line, i) => {
|
||||
if (/never tell the owner/i.test(line)) return; // the rule quoting what not to say
|
||||
for (const re of HANDOFF) if (re.test(line)) hits.push(`${f}:${i + 1}: ${line.trim().slice(0, 120)}`);
|
||||
});
|
||||
}
|
||||
expect(hits).toEqual([]);
|
||||
});
|
||||
|
||||
test('the handoff patterns catch the phrases that cost hours', () => {
|
||||
const bad = ['## Steps (API = storebound, UI = Play Console by hand)', 'ask the owner to click Next on each page',
|
||||
'upload them in the experiment form yourself', 'Do that part by hand (the manual steps follow)',
|
||||
'The owner opens App content > Data safety > Export to CSV', 'prints the list for the owner to copy'];
|
||||
for (const b of bad) expect(HANDOFF.some(re => re.test(b))).toBe(true);
|
||||
const ok = ['drive the page yourself (Claude in Chrome)', 'the owner presses Publish', 'the owner signs in once',
|
||||
'press Create app yourself', 'Granting them is the owner\'s (a permission grant)'];
|
||||
for (const o of ok) expect(HANDOFF.some(re => re.test(o))).toBe(false);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue