Screenshot guardrails: name every screenshot not COMPLETE on 409 ASSET_IN_POST_PROCESSING (submit, validate; stuck after 5 min in UPLOAD_COMPLETE), apple screenshots --repair-stuck replaces only those in place, part uploads without Expect: 100-continue (failed part deletes the reservation, one retry, never committed), storebound api --confirm <operationId> for agents' plain writes (never owner-only)

This commit is contained in:
CRTkafa 2026-10-21 12:40:26 +07:00
parent 164182012f
commit 00756e6908
19 changed files with 475 additions and 45 deletions

View file

@ -2,6 +2,7 @@
// these functions turn it into an ordered list of findings. Order = the order you would fix things in.
import { consoleLink, consoleUrl } from './console-links';
import { describePending, type Pending, repairable } from '../apple/screenshot-health';
import { type FixAction, fixAppleListing, fixPlayListing, fixReviewDetails } from './fix-actions';
import { iphoneDuoNote, macNote } from '../shots/spec';
@ -59,6 +60,9 @@ export interface AppleSnapshot {
version: { versionString: string; state: string; copyright?: string | null; platform?: string } | null;
/** Header and Search Results files uploaded but not approved yet, per locale and placement (apple creative-assets). */
creativeWaiting?: { locale: string; placement: string; file: string; text: string }[];
/** Screenshots of the version that are not COMPLETE (cli/apple/screenshot-health.ts): a submit answers 409
* ASSET_IN_POST_PROCESSING while any is left. */
screenshotsPending?: Pending[];
/** Editable or rejected versions of the app's other platforms (an app's macOS version has its own state). */
otherPlatformVersions?: { versionString: string; state: string; platform: string }[];
/** app.copyright from the config (undefined: not set). */
@ -211,6 +215,13 @@ export function appleRules(s: AppleSnapshot): Finding[] {
else if (EDITABLE.includes(s.version.state)) add('ok', 'version', `version ${vl}: ${s.version.state}`);
else if (IN_FLIGHT.includes(s.version.state)) add('warn', 'version', `version ${vl} is ${s.version.state} (nothing to prepare)`);
else add('warn', 'version', `version ${vl}: ${s.version.state}`);
{
const pend = s.screenshotsPending ?? [];
const lines = describePending(pend);
pend.forEach((p, i) => repairable(p)
? add('blocker', 'screenshot-stuck', lines[i]!, 'storebound apple screenshots --repair-stuck --dry, then without --dry (replaces only this screenshot at its position)')
: add('warn', 'screenshot-processing', lines[i]!, 'wait a few minutes: a submit answers 409 ASSET_IN_POST_PROCESSING until it is COMPLETE'));
}
for (const w of s.creativeWaiting ?? []) add('warn', 'creative-waiting', `${w.locale} ${w.placement}: ${w.file} ${w.text}`, 'storebound apple creative-assets (a re-run places it once approved; --add-for-review sends it to review)');
for (const o of s.otherPlatformVersions ?? []) {
const name = PLATFORM_NAMES[o.platform] ?? o.platform;