Commit graph

226 commits

Author SHA1 Message Date
CRT
b39e44e6ab console fill: one app shown twice is one app; App Privacy opens by app id via the API
`console fill apple-app-privacy` without apple.appId stopped at "the app
in the list" with "more than one app matches: X | X" for an account with
one app: the Apps grid names each app twice (the icon link's aria-label
and the title link), both opening the same /apps/<id>/... page.

- pickApp tells hits apart by the app they open (/apps/<id>, else the
  link target), not by name. Two apps of one name with different targets
  still stop and are listed.
- Without apple.appId, but with App Store Connect API credentials, the
  app id is looked up from apple.bundleId (GET /v1/apps?filter[bundleId],
  as `apple status` does), cached in .storebound/console-app-ids.json, and
  App Privacy opens by deep link. Without credentials, or when the lookup
  fails, the Apps list by name is used, and the log says so.

Fixture asc-apps-card.html (a card with the name in the title and an
aria-label); tests for both paths.
2026-10-12 06:32:21 +08:00
CRT
de243cdbd9 tests: profile persistence runs in a real Chrome, in its own shard
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.
2026-10-12 06:27:42 +08:00
CRT
e21e274c2a browser: one launch resolver; console fill never reports a hidden error
`console fill --fresh-profile` failed with "Executable doesn't exist ...
chromium-1187" when only Playwright's headless shell was downloaded,
although Google Chrome was installed (also with STOREBOUND_CHROME set).
The Chrome launch did run, but failed because an earlier storebound run
still held the profile, and the fallback rethrew the FIRST error.

Every launch (renders, captures, console profile and copy modes, the
desktop sidecar) now goes through one resolver that checks the exact
executable before trying it:
- headless: STOREBOUND_CHROME, headless shell, full Chromium, Chrome
- visible / persistent: STOREBOUND_CHROME, Google Chrome, full Chromium
  (channel "chromium"); never the headless shell
- copy mode: Google Chrome only
A missing browser is skipped; an installed one that fails reports its own
error; nothing usable names what was looked for plus the doctor /
playwright install hint. A profile whose SingletonLock names a live
process is reported before launching.
2026-10-12 06:17:19 +08:00
CRT
d531626836 Merge remote-tracking branch 'origin/main' into play-app-record
# Conflicts:
#	CHANGELOG.md
2026-10-12 05:26:34 +08:00
CRT
04fb0089b5 Merge remote-tracking branch 'origin/main' into play-app-record
# Conflicts:
#	CHANGELOG.md
#	docs/pitfalls.md
#	skills/store-pitfalls/SKILL.md
#	tests/console-fill.test.ts
2026-10-12 05:24:52 +08:00
CRT
7746a984ec Merge remote-tracking branch 'origin/main' into shots-liga
# Conflicts:
#	CHANGELOG.md
#	cli/index.ts
2026-10-12 05:24:19 +08:00
CRT
af08d7113a shots check: ligatures no longer read as system-font glyphs (probe spans shaped as one run); --help on every command and group, unknown flags rejected before anything runs
Root cause: the per-character font probes were inline spans side by side, so Chrome shaped f + i into the fi ligature across them and the lone i probe reported no glyph of ours. Each probe is now its own block. The Google Fonts text= subsets keep the GSUB ligatures; regression test with a real Montserrat text= subset.

--help / -h prints the command's usage and exits 0 before any config, render or network; unknown flags exit 2 with the usage (cli/data/flags.json from tools/gen-flags.ts). Command tables moved to cli/commands.ts; ads apple reachable again; shots render --scenes rejects unknown ids at once.
2026-10-12 05:23:37 +08:00
CRT
c51b689070 Merge remote-tracking branch 'origin/main' into fast-ci 2026-10-12 05:16:52 +08:00
CRT
29e1ec799e Merge remote-tracking branch 'origin/main' into flaky-console 2026-10-12 05:11:33 +08:00
CRT
d9515fa8f0 Merge remote-tracking branch 'origin/main' into fast-ci
# Conflicts:
#	CHANGELOG.md
#	tests/site-overflow.test.ts
2026-10-12 05:10:37 +08:00
CRT
44db357b73 ci:quick: browser suites only for nearby imports (full ci runs them always) 2026-10-12 05:08:23 +08:00
CRT
2508d9031d Merge remote-tracking branch 'origin/main' into flaky-console 2026-10-12 05:06:36 +08:00
CRT
66bf1f82eb scan: TODO / TBD / FIXME / XXX count as placeholder markers only in capitals ('todo' is a real keyword for to-do apps) 2026-10-12 05:06:23 +08:00
CRT
5e1357116d fast ci: task graph runner, sharded tests balanced by recorded durations, ci:quick (typecheck + related tests + scrub), Rust only when src-tauri / sidecar build changed, event waits instead of sleeps 2026-10-12 05:05:26 +08:00
CRT
fd82db0d75 Merge remote-tracking branch 'origin/main' into aso-plus 2026-10-12 04:59:49 +08:00
CRT
a7569deb26 Merge remote-tracking branch 'origin/main' into flaky-console
# Conflicts:
#	tests/site-overflow.test.ts
2026-10-12 04:54:13 +08:00
CRT
a5295db539 browser tests: deterministic under load
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)
2026-10-12 04:54:07 +08:00
CRT
bd15f790cc site overflow test: 60 s for closing Chromium (the 5 s hook default times out on a busy machine) 2026-10-12 04:50:36 +08:00
CRT
3fb3f2108a Merge remote-tracking branch 'origin/main' into aso-plus
# Conflicts:
#	CHANGELOG.md
2026-10-12 04:24:52 +08:00
CRT
96d1e6b62d Merge remote-tracking branch 'origin/main' into idem-listing 2026-10-12 04:24:49 +08:00
CRT
a2009fa7ac idempotency: apple listing findOrCreate / createOnce, play listing re-plan in the edit, data-safety hash, twice-run tests for the last open rows 2026-10-12 04:24:45 +08:00
CRT
e38f68fa33 Merge origin/main into local-fonts 2026-10-12 04:15:26 +08:00
CRT
354daba672 shots fonts: local font files (title / body / fallback) with cmap coverage, served in place, hash in fonts.json, license note 2026-10-12 04:15:19 +08:00
CRT
17f4413afa Merge remote-tracking branch 'origin/main' into aso-plus
# Conflicts:
#	CHANGELOG.md
#	docs/pitfalls.md
#	skills/store-pitfalls/SKILL.md
2026-10-12 04:13:48 +08:00
CRT
d68028caba Merge remote-tracking branch 'origin/main' into play-app-record
# Conflicts:
#	CHANGELOG.md
#	docs/pitfalls.md
#	skills/store-pitfalls/SKILL.md
2026-10-12 04:13:35 +08:00
CRT
124e3097ec listing check: App Store keywords shown and limited in UTF-8 bytes (96/100 B), other fields in characters 2026-10-12 04:10:28 +08:00
CRT
b65843828b Merge remote-tracking branch 'origin/main' into aso-plus
# Conflicts:
#	CHANGELOG.md
2026-10-12 04:09:46 +08:00
CRT
7e26941ffc aso: competitors, suggest and audit from official data; ASO card on the Growth tab
- aso competitors: top apps per keyword from the iTunes Search API (name, developer,
  rating count, release / update dates, localized genre), coverage gaps (words of 2+
  developers), new entrants vs the last snapshot (.storebound/aso/competitors/)
- aso suggest: candidates from own text, competitor names, localized category names and
  Apple Ads keyword suggestions (POST /v1/suggestions/keywords/query, relative 0-100
  popularity, only with credentials); 100-byte keyword field per locale as a diff,
  --write marks it a draft that check --aso and aso audit report
- aso audit: check --aso, free keyword room, rank trend arrows, gaps, Play short
  description / density, App Store conversion, PPO / Play experiment ideas, next 3 actions
- MCP: read-only aso_competitors, aso_suggest, aso_audit; desktop ASO card (visx rank chart)
- docs: README, aso-basics, store-pitfalls (Search API order, no Play search API), CHANGELOG;
  demo-app listing files; tests on recorded Search API and mocked Ads answers
2026-10-12 04:09:34 +08:00
CRT
4533e3e1c4 app privacy: one Apple purpose per Play purpose (advertising is Third-Party Advertising only; Developer's Advertising only from the owner), appPrivacy.types (owner answers per Apple type id: certain in console fill, proposed by scan without linked / tracking, compared by check with Info.plist and PrivacyInfo.xcprivacy) 2026-10-12 04:07:15 +08:00
CRT
8f41ed4c02 Merge origin/main into idempotency 2026-10-12 04:01:25 +08:00
CRT
00cf2ed341 idempotency: WIP 2026-10-12 04:00:58 +08:00
CRT
704231457f Merge remote-tracking branch 'origin/main' into play-app-record
# Conflicts:
#	CHANGELOG.md
2026-10-12 03:58:50 +08:00
CRT
1150d4e4e6 Merge origin/main into shots-speed
# Conflicts:
#	CHANGELOG.md
2026-10-12 03:49:58 +08:00
CRT
5cb5dc2c32 shots capture / render: --concurrency, per-frame timing, per-language page reuse, input-hash cache
Web capture runs frames in parallel browser contexts (default from the CPU count, lower for GPU-heavy capture),
logs n/total + ETA and goto / waitFor / eval / delay / screenshot per frame, writes .storebound/capture-report.json
with the slowest frames and steps. shots.capture.session 'per-language' boots the app once per language and device
and switches shots via pushState / popstate (navigate 'spa') or goto (navigate 'reload'), falling back to a fresh
page when a precondition fails. .storebound/capture-cache.json skips frames with unchanged inputs; --only-missing,
--force. shots render renders with --concurrency pages and async ffmpeg.
2026-10-12 03:49:53 +08:00
CRT
75d6f4cb71 console fill play-app-record: Play Console's Create app form (account picked by developerId / workspace / play.developerAccount, else stop and list; Create app opener allowlisted only on the app list, never in the form, EN + TR; name, default language, app or game, free or paid as an owner check; declarations never ticked; package name set by the first AAB upload) 2026-10-12 03:48:20 +08:00
CRT
143325c033 pitfalls: apple listing dry run prints a plan now, its allow entry removed 2026-10-12 03:42:45 +08:00
CRT
d466d4a3c2 Merge remote-tracking branch 'origin/main' into apple-name
# Conflicts:
#	CHANGELOG.md
2026-10-12 03:40:51 +08:00
CRT
866aa4a041 Merge remote-tracking branch 'origin/main' into pitfalls
# Conflicts:
#	cli/apple/iap-review.ts
2026-10-12 03:30:34 +08:00
CRT
59e60960b0 pitfalls: store-pitfalls skill and docs/pitfalls.md, store list lag warnings (apple iap-review exits 1), dryPlan table and a scan for count-only dry runs 2026-10-12 03:29:53 +08:00
CRT
6c4f8a4551 Merge remote-tracking branch 'origin/main' into apple-name
# Conflicts:
#	CHANGELOG.md
2026-10-12 03:29:53 +08:00
CRT
b88648499e apple listing, play listing, apple appinfo: the dry run prints a real plan (version decision, old -> new per field, draft locales skipped); the real run asks and applies exactly it 2026-10-12 03:29:38 +08:00
CRT
221f08aaf6 apple iap-review: size check before upload, delivery state read back after (FAILED shown with Apple's reason), dry run names why it would upload, MISSING_METADATA explained per part; check flags non-screenshot sizes offline 2026-10-12 03:24:41 +08:00
CRT
5afe4613c4 apple.name: the App Store name when the plain name is taken; console fill, apple listing, pull, check (30-char error, same-name hint), scan use it 2026-10-12 03:23:43 +08:00
CRT
296aa6a6ae Merge origin/main into shots-glyphs 2026-10-12 03:13:05 +08:00
CRT
8bfa49807d Merge origin/main into shots-glyphs
# Conflicts:
#	CHANGELOG.md
2026-10-12 03:05:32 +08:00
CRT
d942275920 shots: glyph coverage check per language, automatic Noto fallbacks, check errors on fallback / system-font glyphs
Lilita One lacks most of Latin Extended-A (Turkish s-cedilla, g-breve, dotted I ...), so Turkish titles were drawn
with a silent browser fallback while shots check passed. shots fonts now reads the cmap of every face (pure TS,
TTF/OTF/WOFF/WOFF2), adds a Noto fallback per missing character or fails with language + characters; render
measures which face drew each character (CDP probes) and records it in report.json; check errors on fallbacks the
config did not choose (shots.fonts.fallback) and on system-font glyphs. Default game title font: Paytone One.
2026-10-12 03:05:23 +08:00
CRT
8186b25575 console fill: User Access radios found under a plain heading (real App Store Connect), a lasting partial miss fills every field found and leaves only the missing ones to the owner 2026-10-12 03:05:11 +08:00
CRT
9e15cf43e3 Merge remote-tracking branch 'origin/main' into console-signin 2026-10-12 02:54:50 +08:00
CRT
21c0c2ed60 console fill: sign-in detected by URL, frame and text; keeps watching after the fallback; session kept across relaunches; one login across Play developer accounts and App Store Connect teams 2026-10-12 02:54:48 +08:00
CRT
930f960318 teaser v6: 55.5 s, v5 kept, its desktop part grown to four scenes
Portfolio (every app, both stores, rollout %, crash sparklines), the Growth and
Health charts with a real hover sweep (one captured frame per hovered day, the
pointer follows the recorded positions), the Prices matrix (both stores per
country, gaps marked), then v5's release timeline and 0 blockers. All frames are
real fixture-mode captures (desktop.ts). Tests: scenes 4-5 s, 50-60 s total,
captions >= 3 s, every desktop frame captured by desktop.ts and present.
2026-10-12 02:32:53 +08:00