- one version: package.json's version is the desktop app's too (desktopVersion removed); tools/desktop-version.ts
keeps the plugin manifests and the app's copies equal, desktop-release publish refuses another version, release
order app first then npm publish; the unpublished desktop 0.1.0 candidate is noted in the docs and CHANGELOG
- storebound desktop installs (per user, no admin: macOS DMG -> /Applications or ~/Applications, Windows NSIS /S,
Linux AppImage + .desktop with the storebound:// handler), updates an older app, notes a newer one (downgrade only
with --force), asks once ([Y/n], --yes, exit 3 without a terminal), opens on the folder; --dry / --json / --download;
the install steps are pure plans (cli/lib/desktop-install.ts); the version's own manifest dl/<version>/latest.json
- credentials: one store, the CLI's credential profiles in ~/.storebound/credentials; the desktop writes and reads
them (profiles.rs, files 0600), moves old keychain accounts into profiles on first start, shows profiles the CLI
made; precedence env > named profile > project file > default profile; config `account`, "account" in the
project's credentials.json; storebound accounts list | import (dedup by key id / service account e-mail, key files
copied 0600, project file keeps keystore and review contact, backup, --dry, never prints values) | use
- app folders: one list ~/.storebound/projects.json shared by the desktop (registry.rs), storebound desktop,
apps folders | add | remove, ws init and ws without a workspace file
- desktop: notice when a folder pins another storebound version; storebound-desktop --version
- tests: version drift, desktop decisions and per-OS plans, credential precedence and import, registry (TS + Rust),
keychain migration and profile round trip (Rust), boot check with old keychain state and the new shared state
confirm() prints 'declined: <reason>' and exits 3 whenever the answer is no or nobody can answer (not a
terminal without --yes, serve without the owner's dialog), so no command reports success after declining.
flow run stops at such a step with 'step N declined: <reason>' (status declined), never ok. flow run
--apply --yes passes --yes to write steps only; --yes without --apply is refused. Pitfall 24.
The two "session cookie survives closing and relaunching storebound's own
profile" tests failed with Playwright's headless shell, which ignores
--restore-last-session. They now live in tests/console-persist.test.ts
and launch the same browser kind console fill uses for its profile (the
resolver's "visible" kind: Google Chrome, else the full Chromium; headless
here, so no window). They skip with the reason only when neither is
installed. All other browser tests keep the fast headless shell. The file
is HEAVY in tools/ci-plan.ts, so it never shares a shard with another
browser suite.
The afterAll hook of tests/console-fill.test.ts timed out (30 s) in 2 of 3
runs with 10 CPU hogs. Cause: Google Chrome (the fallback when playwright's
Chromium is not downloaded) hangs in its own shutdown after loading http
pages until its 10 s teardown watchdog fires; under load that passed 30 s.
- tests/helpers/browser.ts: one shared launch per file as a browser server
with a 60 s launch timeout, killed at the end (throwaway profile, nothing
to flush); a launch timeout fails instead of silently skipping; contexts
and engine runs tracked per test and closed in afterEach (capped);
event-driven waits for engine log lines
- console-fill: explicit test timeouts, slow tests marked, waits expected
to succeed get a long cap (they return at once), sign-in / watching
navTimeoutMs 1.5 s -> 5 s, persistent-profile Chromium closed in finally,
temp account dirs removed
- site-overflow, console-session: same plumbing (site-overflow's afterAll
had bun's 5 s default)
- console session: launchTimeoutMs option (tests only)
Nine scenes of 6-7 s, one slow camera move each, soft dissolves, one plain-English caption per scene at the top
(on screen at least 4 s): the stores' to-do list and one rejection mail, `init` in an empty folder, the agent prompt
and `release plan` (25 steps), store text and renders in 7 sizes x 4 languages, `play products --dry` and
`catalog diff`, the scan's declarations proposal with the ask-owner line, three findings with plain reasons turning
green, the desktop release timeline and Store readiness "No blockers", Submit and the end card.
Every CLI line is real output: tests/teaser.test.ts runs each command (store answers from
tests/helpers/teaser-store-mock.ts, preloaded through bunfig.toml, never the network) and checks scene lengths,
caption holds, the 55-65 s total and 16:9 only. The vertical output is gone; the web version targets 4.5 MB.
Calmer music (D major pads, soft pluck, bells on scene changes). desktop.ts adds the Store readiness frame.
- apple testflight wait --build N (progress, timeout, exit 0/1/7) and expire --keep N | --older-than D (dry run, asks)
- apple iap-submit: IAP / subscription / group versions into a review submission; first of a type only with the app
version (--with-version), --no-submit keeps the draft; read-only MCP plan
- apple listing pull, play listing pull (diff, --write), catalog pull (config proposal, never rewritten)
- whats-new --languages / check / apply: one file per language, agent or hook translation, per-store limits
- apple offer-codes, win-back, promoted, preorder; Play pre-registration as a guide (no API)
- apple cpp and apple events: list, create, upload, submit (asks)
- reports: Apple sales / finance, Play earnings / sales into .storebound/reports with summary and CSV
- triage: TestFlight crash / feedback and Play error reports grouped by signature, device, OS
- aso rank: iTunes Search API ranks and competitors, rate limited
- ads scan: AdAttributionKit / SKAdNetwork Info.plist and source checks
- tests against recorded, sanitized answers; skills, README, CHANGELOG