From e539587de3ec76fb7595acc71b3d2ab333b8e933 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 13:18:07 -0700 Subject: [PATCH 01/13] feat(gstack2): Apple App Store release adapter for /ship Ship-tree reference contract APPLE-RELEASE.md: paid-membership gate, native-toolchain preflight (signing, versioning, deps, validation blockers), archive/upload via xcodebuild with App Store Connect API key auth, uploads bound to the durable external-effects wrapper, and App Store Connect completion routed through THIRD-PARTY-ACTIONS consent. Dispatcher gains protocol line 10 to load it for Apple targets; parity pins the gate, upload binding, and no-new-dependency rule (5080 -> 5083). Co-Authored-By: Claude Fable 5 --- scripts/gstack2/generate-skill-tree.ts | 40 +++++++++++++++++++++++++- scripts/gstack2/run-parity.ts | 14 ++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index 13a6cc749e..237693d98d 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -202,7 +202,7 @@ function rootSkill(dispatcher: DispatcherDefinition): string { const supplemental = dispatcher.name === 'qa' ? '\n9. When `system-functional` is active, read `references/SYSTEM-FUNCTIONAL.md` completely and execute it alongside the selected preserved specialists.\n' : dispatcher.name === 'ship' - ? '\n9. Before push, PR creation/update, merge, deploy, rollback, release publication, or external notification, read `references/EXTERNAL-EFFECTS.md` and execute the action through its durable state wrapper.\n' + ? '\n9. Before push, PR creation/update, merge, deploy, rollback, release publication, or external notification, read `references/EXTERNAL-EFFECTS.md` and execute the action through its durable state wrapper.\n10. When the release target is an Apple platform app (an `.xcodeproj`, `.xcworkspace`, or app-product Swift package is present), read `references/APPLE-RELEASE.md` before release preparation and follow its App Store journey end to end.\n' : dispatcher.name === 'plan' ? '\n9. Classify the Scale header line from the Build scale section before any questioning begins. Every planning specialist applies its proportional-planning judgment port to that scale.\n' : ''; @@ -636,6 +636,43 @@ Do not put secrets in run IDs, effect keys, or command arguments. Existing appro `; } +function appleReleaseContract(): string { + return `${GENERATED} +# Apple App Store release + +Applies when the ship target is an Apple platform app: the repository contains an \`.xcodeproj\` or \`.xcworkspace\`, or a Swift package with an app product. This adapter extends the preserved ship judgment to the App Store journey end to end; it replaces no gate, and every upload or submission remains an external effect executed through \`references/EXTERNAL-EFFECTS.md\`. + +Work only with the native Apple toolchain (\`xcodebuild\`, \`xcrun\`, \`agvtool\`). Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project. + +## Membership gate + +Before any archive work, ask one explicit question: does the user have a paid Apple Developer Program membership (US$99/year)? App Store distribution and TestFlight both require it. + +- Yes: continue. +- No: STOP the App Store path. Offer to walk enrollment at developer.apple.com through \`references/THIRD-PARTY-ACTIONS.md\` (enrollment is a purchase the user completes themselves and can take a day or two to activate), or name the free-account ceiling honestly: personal-team signing installs only on the user's own devices and expires after 7 days, with no TestFlight and no App Store. + +## Release preflight + +Resolve and verify before archiving. Fix what the printed mutation boundary authorizes; report everything else as a blocking finding. + +- Signing: development team set on the app target, automatic signing enabled (or a valid distribution certificate and provisioning profile), bundle identifier decided. +- Versioning: a marketing version users should see and a build number strictly greater than any build already uploaded for that version. +- Dependencies: \`xcodebuild -resolvePackageDependencies\` succeeds; if a \`Podfile\` or \`Cartfile\` exists, its install step has been run and lockfiles are current. +- App Store validation blockers: complete app icon set including the 1024pt marketing icon, launch screen, a usage-description string for every privacy-gated API the app touches, required privacy manifests, an export-compliance answer (\`ITSAppUsesNonExemptEncryption\`), and a sane deployment target. + +## Archive, validate, upload + +1. Archive the Release configuration: \`xcodebuild archive -scheme -destination 'generic/platform=iOS' -archivePath .xcarchive\` (substitute the actual platform). +2. Author an export-options plist with method \`app-store-connect\`. Prefer \`destination: upload\`, which validates and uploads in one supported step; \`destination: export\` plus the Transporter app is the fallback. +3. Authenticate with an App Store Connect API key (\`-authenticationKeyPath\`, \`-authenticationKeyID\`, \`-authenticationKeyIssuerID\`). The \`.p8\` key is a secret under the \`THIRD-PARTY-ACTIONS.md\` rules: stored outside the repository, referenced by path, never echoed. +4. The upload is an external effect: run it through the durable state wrapper with a key like \`appstore.upload..\`. Never re-upload on ambiguity; inspect App Store Connect for the build first. + +## App Store Connect completion + +Everything the CLI cannot finish lives in App Store Connect: the app record (name, bundle ID, SKU, primary language), screenshots per required device size, description and keywords, support URL, privacy nutrition labels, age rating, pricing and availability, attaching the uploaded build, and Submit for Review. Offer to drive these through \`references/THIRD-PARTY-ACTIONS.md\` with its per-task consent gate, or hand over a complete manual checklist covering every field App Review requires. Offer a TestFlight distribution of the uploaded build as an intermediate step before review submission. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. +`; +} + function writeSharedContracts(): void { const bootstrap = fs.readFileSync(path.join(ROOT, 'runtime', 'runtime-bootstrap.mjs')); const browserChoice = fs.readFileSync(path.join(ROOT, 'runtime', 'browser-choice.mjs')); @@ -657,6 +694,7 @@ function writeSharedContracts(): void { } write(path.join(ROOT, 'skills', 'qa', 'references', 'SYSTEM-FUNCTIONAL.md'), systemFunctionalContract()); write(path.join(ROOT, 'skills', 'ship', 'references', 'EXTERNAL-EFFECTS.md'), externalEffectsContract()); + write(path.join(ROOT, 'skills', 'ship', 'references', 'APPLE-RELEASE.md'), appleReleaseContract()); } interface RenderedModuleRecord { diff --git a/scripts/gstack2/run-parity.ts b/scripts/gstack2/run-parity.ts index 743894b504..e7b8e71658 100644 --- a/scripts/gstack2/run-parity.ts +++ b/scripts/gstack2/run-parity.ts @@ -31,7 +31,7 @@ const ALLOWED_DISPOSITIONS = new Set(['VERBATIM_PORT', 'MECHANICAL_PORT', 'JUDGM // format, dispatcher load, consent/secret content). Extending the #886 // overlay to the review specialists (review, plan-design-review, // design-review) added 6 more (2 per newly targeted module). -export const EXPECTED_PARITY_CHECKS = 5080; +export const EXPECTED_PARITY_CHECKS = 5083; function sha256(value: string | Uint8Array): string { return createHash('sha256').update(value).digest('hex'); @@ -206,6 +206,18 @@ export function runParity(): ParityResult { check(effects.includes('gstack state effect') && effects.includes('Never retry automatically'), 'Ship external-effect protocol lost durable claim or no-repeat behavior'); } check(fs.readFileSync(path.join(ROOT, 'skills', 'ship', 'SKILL.md'), 'utf8').includes('references/EXTERNAL-EFFECTS.md'), 'Ship dispatcher does not bind external actions to durable state'); + const appleReleasePath = path.join(ROOT, 'skills', 'ship', 'references', 'APPLE-RELEASE.md'); + check(fs.existsSync(appleReleasePath), 'Ship lacks the Apple App Store release adapter'); + if (fs.existsSync(appleReleasePath)) { + const apple = fs.readFileSync(appleReleasePath, 'utf8'); + check( + apple.includes('paid Apple Developer Program membership') + && apple.includes('The upload is an external effect') + && apple.includes('the release itself adds no new dependency'), + 'Apple release adapter lost its membership gate, durable-upload binding, or no-new-dependency rule', + ); + } + check(fs.readFileSync(path.join(ROOT, 'skills', 'ship', 'SKILL.md'), 'utf8').includes('references/APPLE-RELEASE.md'), 'Ship dispatcher does not load the Apple release adapter for Apple targets'); check(files(path.join(ROOT, 'evals', 'parity', 'contracts'), '.json').length === 55, 'Contract fixture count is not 55'); const baselineRenders = json(path.join(ROOT, 'evals', 'parity', 'baseline-render-hashes.json')); From 80d09dcb02a718e3982bd81ee664dd53a42842db Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 13:18:12 -0700 Subject: [PATCH 02/13] chore(gstack2): regenerate skill tree for Apple release adapter Co-Authored-By: Claude Fable 5 --- docs/gstack-2/JUDGMENT-PARITY.md | 2 +- evals/parity/transcripts/policy-units.json | 2 +- skills/ship/SKILL.md | 1 + skills/ship/references/APPLE-RELEASE.md | 33 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 skills/ship/references/APPLE-RELEASE.md diff --git a/docs/gstack-2/JUDGMENT-PARITY.md b/docs/gstack-2/JUDGMENT-PARITY.md index 506ac0d64b..0e10f254ff 100644 --- a/docs/gstack-2/JUDGMENT-PARITY.md +++ b/docs/gstack-2/JUDGMENT-PARITY.md @@ -2,7 +2,7 @@ Parity is executable, not a prose claim. Run `bun run scripts/gstack2/run-parity.ts` or the dedicated Bun tests. -The pinned release inventory passes **5,080 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **78 assets**. +The pinned release inventory passes **5,083 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **78 assets**. The suite verifies: diff --git a/evals/parity/transcripts/policy-units.json b/evals/parity/transcripts/policy-units.json index 3a211c84a3..ba80508a30 100644 --- a/evals/parity/transcripts/policy-units.json +++ b/evals/parity/transcripts/policy-units.json @@ -279,7 +279,7 @@ "prompt_sha256": "a01bb977de84e53d8ce3dfa427bcc93d73c6e449cd4e9c1ff63b436fd41fb0d1", "semantic_attempt_sha256": "ce5c64c62c3ff9b60949f34717dffbc908f62ce30f8a4a48ec182eba4363a206" }, - "policy_sha256": "0052fa07b92825e223b8e070d33b628d0e32429c2a37f7e059e8aa456c81bb1a", + "policy_sha256": "0fe444a11121402f6ee6609d7a514478d3bcf9416b40276f4717c32719082567", "policy_present": true, "prompt_is_not_authority_input": true, "verdict": "PASS" diff --git a/skills/ship/SKILL.md b/skills/ship/SKILL.md index f2ea03a6cb..43cb1b4f54 100644 --- a/skills/ship/SKILL.md +++ b/skills/ship/SKILL.md @@ -34,6 +34,7 @@ Web context: 8. At exit, report completed artifacts, evidence, unresolved decisions, skipped modules with reasons, and any blocked gate. 9. Before push, PR creation/update, merge, deploy, rollback, release publication, or external notification, read `references/EXTERNAL-EFFECTS.md` and execute the action through its durable state wrapper. +10. When the release target is an Apple platform app (an `.xcodeproj`, `.xcworkspace`, or app-product Swift package is present), read `references/APPLE-RELEASE.md` before release preparation and follow its App Store journey end to end. ## Top-level modes diff --git a/skills/ship/references/APPLE-RELEASE.md b/skills/ship/references/APPLE-RELEASE.md new file mode 100644 index 0000000000..6a766d47a3 --- /dev/null +++ b/skills/ship/references/APPLE-RELEASE.md @@ -0,0 +1,33 @@ + +# Apple App Store release + +Applies when the ship target is an Apple platform app: the repository contains an `.xcodeproj` or `.xcworkspace`, or a Swift package with an app product. This adapter extends the preserved ship judgment to the App Store journey end to end; it replaces no gate, and every upload or submission remains an external effect executed through `references/EXTERNAL-EFFECTS.md`. + +Work only with the native Apple toolchain (`xcodebuild`, `xcrun`, `agvtool`). Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project. + +## Membership gate + +Before any archive work, ask one explicit question: does the user have a paid Apple Developer Program membership (US$99/year)? App Store distribution and TestFlight both require it. + +- Yes: continue. +- No: STOP the App Store path. Offer to walk enrollment at developer.apple.com through `references/THIRD-PARTY-ACTIONS.md` (enrollment is a purchase the user completes themselves and can take a day or two to activate), or name the free-account ceiling honestly: personal-team signing installs only on the user's own devices and expires after 7 days, with no TestFlight and no App Store. + +## Release preflight + +Resolve and verify before archiving. Fix what the printed mutation boundary authorizes; report everything else as a blocking finding. + +- Signing: development team set on the app target, automatic signing enabled (or a valid distribution certificate and provisioning profile), bundle identifier decided. +- Versioning: a marketing version users should see and a build number strictly greater than any build already uploaded for that version. +- Dependencies: `xcodebuild -resolvePackageDependencies` succeeds; if a `Podfile` or `Cartfile` exists, its install step has been run and lockfiles are current. +- App Store validation blockers: complete app icon set including the 1024pt marketing icon, launch screen, a usage-description string for every privacy-gated API the app touches, required privacy manifests, an export-compliance answer (`ITSAppUsesNonExemptEncryption`), and a sane deployment target. + +## Archive, validate, upload + +1. Archive the Release configuration: `xcodebuild archive -scheme -destination 'generic/platform=iOS' -archivePath .xcarchive` (substitute the actual platform). +2. Author an export-options plist with method `app-store-connect`. Prefer `destination: upload`, which validates and uploads in one supported step; `destination: export` plus the Transporter app is the fallback. +3. Authenticate with an App Store Connect API key (`-authenticationKeyPath`, `-authenticationKeyID`, `-authenticationKeyIssuerID`). The `.p8` key is a secret under the `THIRD-PARTY-ACTIONS.md` rules: stored outside the repository, referenced by path, never echoed. +4. The upload is an external effect: run it through the durable state wrapper with a key like `appstore.upload..`. Never re-upload on ambiguity; inspect App Store Connect for the build first. + +## App Store Connect completion + +Everything the CLI cannot finish lives in App Store Connect: the app record (name, bundle ID, SKU, primary language), screenshots per required device size, description and keywords, support URL, privacy nutrition labels, age rating, pricing and availability, attaching the uploaded build, and Submit for Review. Offer to drive these through `references/THIRD-PARTY-ACTIONS.md` with its per-task consent gate, or hand over a complete manual checklist covering every field App Review requires. Offer a TestFlight distribution of the uploaded build as an intermediate step before review submission. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. From ee697d9238185d82e33e37f007a43f941e9dd0c3 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 13:18:57 -0700 Subject: [PATCH 03/13] docs: CHANGELOG + VERSION 1.64.0.0 for Apple App Store release adapter Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80d6f3df9d..6a10e48e75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,42 @@ > completion state and remaining P0 gates. No version bump or release claim is > made here while that status holds. +## [1.64.0.0] - 2026-07-23 + +## **/ship now takes an Apple app from working tree** +## **to App Store submission, start to finish.** + +Point /ship at a repo with an `.xcodeproj`, `.xcworkspace`, or app-product Swift package and it runs the whole Apple release journey instead of stopping at "archive it yourself." First question, before any archive work: do you have a paid Apple Developer Program membership ($99/year)? Without one there is no App Store and no TestFlight, so the skill says that plainly and offers to walk enrollment in your browser rather than letting you discover it after an hour of signing errors. With one, it preflights everything App Store validation actually rejects: signing team, marketing version and build number, resolved package dependencies, the 1024pt icon, privacy usage strings, export compliance. Then it archives and uploads with the native Xcode toolchain, nothing else. No fastlane, no new dependency in your project. + +The finish line lives in App Store Connect, so the skill offers to drive it there too: app record, screenshots, privacy labels, pricing, attaching the build, TestFlight, Submit for Review. Same consent-gated browser flow as API-key registration, or a complete manual checklist if you'd rather click yourself. Uploads run through the durable external-effects wrapper, so a crashed session inspects App Store Connect instead of double-submitting your build. + +### The numbers that matter + +Source: `bun run scripts/gstack2/run-parity.ts` on this release. + +| Metric | Before | After | +|---|---|---| +| /ship coverage of the Apple release journey | archive advice | membership gate through Submit for Review | +| New project dependencies required to release | n/a | 0 | +| Pinned parity checks | 5,080 | 5,083 | + +The +3 checks pin the membership gate, the durable-upload binding, and the no-new-dependency rule, so none of them can quietly regress. + +### What this means for iOS builders + +The distance between "my app works in the simulator" and "my app is in review" used to be a weekend of Apple documentation. Now /ship walks it with you, asks the one question that actually gates everything, and stops exactly where App Review takes over. + +### Itemized changes + +### Added + +- `references/APPLE-RELEASE.md` generated into the ship tree: paid Apple Developer Program membership gate with honest free-account ceilings, native-toolchain release preflight, archive/validate/upload via `xcodebuild` with App Store Connect API key auth, uploads bound to the durable external-effects wrapper, and App Store Connect completion (app record, screenshots, privacy labels, TestFlight, Submit for Review) offered through the consent-gated third-party web-action flow. +- Ship dispatch protocol step 10: Apple platform targets load the adapter before release preparation. + +### For contributors + +- New `appleReleaseContract()` in `scripts/gstack2/generate-skill-tree.ts`; 3 pinned checks in `run-parity.ts` (5,080 to 5,083). + ## [1.63.0.0] - 2026-07-23 ## **"Go register an API key" is no longer your homework.** diff --git a/VERSION b/VERSION index 232d60188a..6a0ed664dd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.63.0.0 +1.64.0.0 From bb6ba674fc1760cbc39bfbf000d429e59872f585 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 14:12:50 -0700 Subject: [PATCH 04/13] fix(gstack2): App Store Connect completion via API CLI, not browser The App Store Connect API covers metadata, screenshots, TestFlight, build attachment, Submit for Review, and status monitoring. The adapter now offers a consent-gated machine-level CLI (asc by rorkai; ittybittyapps and Codemagic equivalents) authenticated with the same API key, submissions bound to the durable wrapper. Browser/manual fallback shrinks to what the API refuses: initial app record, agreements, banking/tax. Co-Authored-By: Claude Fable 5 --- scripts/gstack2/generate-skill-tree.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index 237693d98d..579657ddc9 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -642,7 +642,7 @@ function appleReleaseContract(): string { Applies when the ship target is an Apple platform app: the repository contains an \`.xcodeproj\` or \`.xcworkspace\`, or a Swift package with an app product. This adapter extends the preserved ship judgment to the App Store journey end to end; it replaces no gate, and every upload or submission remains an external effect executed through \`references/EXTERNAL-EFFECTS.md\`. -Work only with the native Apple toolchain (\`xcodebuild\`, \`xcrun\`, \`agvtool\`). Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project. +Build and upload with the native Apple toolchain (\`xcodebuild\`, \`xcrun\`, \`agvtool\`); finish the storefront work with a consent-gated App Store Connect API CLI as described below. Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project — the App Store Connect CLI is a machine tool, installed only with explicit consent. ## Membership gate @@ -669,7 +669,11 @@ Resolve and verify before archiving. Fix what the printed mutation boundary auth ## App Store Connect completion -Everything the CLI cannot finish lives in App Store Connect: the app record (name, bundle ID, SKU, primary language), screenshots per required device size, description and keywords, support URL, privacy nutrition labels, age rating, pricing and availability, attaching the uploaded build, and Submit for Review. Offer to drive these through \`references/THIRD-PARTY-ACTIONS.md\` with its per-task consent gate, or hand over a complete manual checklist covering every field App Review requires. Offer a TestFlight distribution of the uploaded build as an intermediate step before review submission. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. +The App Store Connect API covers nearly all remaining work; drive it from a CLI, not a browser. Offer to install a dedicated App Store Connect CLI with one explicit consent question: \`asc\` (rorkai/App-Store-Connect-CLI, \`brew install asc\`) is the default offer; ittybittyapps/appstoreconnect-cli and codemagic-ci-cd cli-tools are equivalents if the user prefers them. It is a machine-level tool authenticated with the same App Store Connect API key, never a project dependency, and its telemetry is disabled unless the user opts in. If the user already has dedicated App Store Connect agent skills installed (for example rorkai/app-store-connect-cli-skills via the standard skills installer), defer to those flows instead of duplicating them. + +Through the CLI: description, keywords, and localizations; screenshot upload per required device size; TestFlight groups and testers as an intermediate distribution before review; attaching the uploaded build to the version; Submit for Review; and review-status monitoring afterward. Submission is an external effect like the upload: run it through the durable state wrapper with a key like \`appstore.submit..\`. + +The API cannot create the initial app record (name, bundle ID, SKU, primary language), accept agreements, or configure banking and tax; those stay on the App Store Connect website, offered through \`references/THIRD-PARTY-ACTIONS.md\` or as a short manual checklist. The same fallback applies to any individual field the chosen CLI cannot set. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. `; } From 8f22764c3c3c341260537305bc8154ed10614f39 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 14:12:50 -0700 Subject: [PATCH 05/13] chore(gstack2): regenerate Apple release adapter Co-Authored-By: Claude Fable 5 --- skills/ship/references/APPLE-RELEASE.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/skills/ship/references/APPLE-RELEASE.md b/skills/ship/references/APPLE-RELEASE.md index 6a766d47a3..17e8a483ff 100644 --- a/skills/ship/references/APPLE-RELEASE.md +++ b/skills/ship/references/APPLE-RELEASE.md @@ -3,7 +3,7 @@ Applies when the ship target is an Apple platform app: the repository contains an `.xcodeproj` or `.xcworkspace`, or a Swift package with an app product. This adapter extends the preserved ship judgment to the App Store journey end to end; it replaces no gate, and every upload or submission remains an external effect executed through `references/EXTERNAL-EFFECTS.md`. -Work only with the native Apple toolchain (`xcodebuild`, `xcrun`, `agvtool`). Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project. +Build and upload with the native Apple toolchain (`xcodebuild`, `xcrun`, `agvtool`); finish the storefront work with a consent-gated App Store Connect API CLI as described below. Never add fastlane or another release manager as a project dependency to ship; the release itself adds no new dependency to the user's project — the App Store Connect CLI is a machine tool, installed only with explicit consent. ## Membership gate @@ -30,4 +30,8 @@ Resolve and verify before archiving. Fix what the printed mutation boundary auth ## App Store Connect completion -Everything the CLI cannot finish lives in App Store Connect: the app record (name, bundle ID, SKU, primary language), screenshots per required device size, description and keywords, support URL, privacy nutrition labels, age rating, pricing and availability, attaching the uploaded build, and Submit for Review. Offer to drive these through `references/THIRD-PARTY-ACTIONS.md` with its per-task consent gate, or hand over a complete manual checklist covering every field App Review requires. Offer a TestFlight distribution of the uploaded build as an intermediate step before review submission. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. +The App Store Connect API covers nearly all remaining work; drive it from a CLI, not a browser. Offer to install a dedicated App Store Connect CLI with one explicit consent question: `asc` (rorkai/App-Store-Connect-CLI, `brew install asc`) is the default offer; ittybittyapps/appstoreconnect-cli and codemagic-ci-cd cli-tools are equivalents if the user prefers them. It is a machine-level tool authenticated with the same App Store Connect API key, never a project dependency, and its telemetry is disabled unless the user opts in. If the user already has dedicated App Store Connect agent skills installed (for example rorkai/app-store-connect-cli-skills via the standard skills installer), defer to those flows instead of duplicating them. + +Through the CLI: description, keywords, and localizations; screenshot upload per required device size; TestFlight groups and testers as an intermediate distribution before review; attaching the uploaded build to the version; Submit for Review; and review-status monitoring afterward. Submission is an external effect like the upload: run it through the durable state wrapper with a key like `appstore.submit..`. + +The API cannot create the initial app record (name, bundle ID, SKU, primary language), accept agreements, or configure banking and tax; those stay on the App Store Connect website, offered through `references/THIRD-PARTY-ACTIONS.md` or as a short manual checklist. The same fallback applies to any individual field the chosen CLI cannot set. After submission, report that App Review typically answers within a day or two and close the run; review outcome is not a gate this workflow can hold open. From a5dcd96c35cca321a7fc9b4e757b69696cad0795 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 14:12:50 -0700 Subject: [PATCH 06/13] docs: CHANGELOG 1.64.0.0 reflects CLI-first App Store Connect completion Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a10e48e75..120ff6b9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ Point /ship at a repo with an `.xcodeproj`, `.xcworkspace`, or app-product Swift package and it runs the whole Apple release journey instead of stopping at "archive it yourself." First question, before any archive work: do you have a paid Apple Developer Program membership ($99/year)? Without one there is no App Store and no TestFlight, so the skill says that plainly and offers to walk enrollment in your browser rather than letting you discover it after an hour of signing errors. With one, it preflights everything App Store validation actually rejects: signing team, marketing version and build number, resolved package dependencies, the 1024pt icon, privacy usage strings, export compliance. Then it archives and uploads with the native Xcode toolchain, nothing else. No fastlane, no new dependency in your project. -The finish line lives in App Store Connect, so the skill offers to drive it there too: app record, screenshots, privacy labels, pricing, attaching the build, TestFlight, Submit for Review. Same consent-gated browser flow as API-key registration, or a complete manual checklist if you'd rather click yourself. Uploads run through the durable external-effects wrapper, so a crashed session inspects App Store Connect instead of double-submitting your build. +The finish line runs through the App Store Connect API, not your browser. The skill offers to install `asc` (rorkai's App Store Connect CLI, one brew command, your own API key, telemetry off) and drives metadata, localizations, screenshots, TestFlight, build attachment, Submit for Review, and status monitoring from the terminal. The browser only appears for the three things Apple's API genuinely refuses: creating the initial app record, agreements, and banking/tax. Uploads and submissions run through the durable external-effects wrapper, so a crashed session inspects App Store Connect instead of double-submitting your build. ### The numbers that matter @@ -36,7 +36,7 @@ The distance between "my app works in the simulator" and "my app is in review" u ### Added -- `references/APPLE-RELEASE.md` generated into the ship tree: paid Apple Developer Program membership gate with honest free-account ceilings, native-toolchain release preflight, archive/validate/upload via `xcodebuild` with App Store Connect API key auth, uploads bound to the durable external-effects wrapper, and App Store Connect completion (app record, screenshots, privacy labels, TestFlight, Submit for Review) offered through the consent-gated third-party web-action flow. +- `references/APPLE-RELEASE.md` generated into the ship tree: paid Apple Developer Program membership gate with honest free-account ceilings, native-toolchain release preflight, archive/validate/upload via `xcodebuild` with App Store Connect API key auth, uploads and submissions bound to the durable external-effects wrapper, and App Store Connect completion (metadata, screenshots, TestFlight, Submit for Review, status monitoring) driven by a consent-gated App Store Connect API CLI (`asc` by default, ittybittyapps and Codemagic equivalents named). Browser/manual fallback only for what the API cannot do: initial app record, agreements, banking/tax. - Ship dispatch protocol step 10: Apple platform targets load the adapter before release preparation. ### For contributors From 36bb3e2023612714b40d030d82f3d95f38ffd312 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:08:51 -0700 Subject: [PATCH 07/13] feat(gstack2): consent-gated store-asset offers in Apple release adapter Missing icon or screenshots trigger one question, never unprompted generation: SnapAI icons (single 1024 source, Xcode derives sizes), aso-appstore-screenshots skill for marketing shots, free local asc framing, or user-supplied assets. Co-Authored-By: Claude Fable 5 --- scripts/gstack2/generate-skill-tree.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index 579657ddc9..c0e3246532 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -667,6 +667,15 @@ Resolve and verify before archiving. Fix what the printed mutation boundary auth 3. Authenticate with an App Store Connect API key (\`-authenticationKeyPath\`, \`-authenticationKeyID\`, \`-authenticationKeyIssuerID\`). The \`.p8\` key is a secret under the \`THIRD-PARTY-ACTIONS.md\` rules: stored outside the repository, referenced by path, never echoed. 4. The upload is an external effect: run it through the durable state wrapper with a key like \`appstore.upload..\`. Never re-upload on ambiguity; inspect App Store Connect for the build first. +## Store assets + +When preflight finds a missing icon, or the storefront step needs screenshots, ask the user first — one question, then act on their choice. Never generate marketing assets or spend the user's image-API budget unprompted. Offer: + +- **App icon**: SnapAI (\`npx snapai\`, the app-icon agent skill) generates a 1024×1024 icon-styled square with the user's own OpenAI key (roughly $0.05–0.19 per icon); Xcode 15+ derives every size from that single image, so no resizer tool is needed. +- **Marketing screenshots**: the aso-appstore-screenshots agent skill (benefit-headline discovery, deterministic scaffold, Nano Banana Pro enhancement with the user's Gemini key, exact App Store dimensions). If installed, follow its workflow rather than reimplementing it. +- **Plain device framing**: \`asc screenshots capture\` and \`asc screenshots frame\` — free, local, upload-normalized output (requires the axe CLI and pinned Koubou). +- **User-supplied assets**: always a valid answer; validate dimensions and move on. + ## App Store Connect completion The App Store Connect API covers nearly all remaining work; drive it from a CLI, not a browser. Offer to install a dedicated App Store Connect CLI with one explicit consent question: \`asc\` (rorkai/App-Store-Connect-CLI, \`brew install asc\`) is the default offer; ittybittyapps/appstoreconnect-cli and codemagic-ci-cd cli-tools are equivalents if the user prefers them. It is a machine-level tool authenticated with the same App Store Connect API key, never a project dependency, and its telemetry is disabled unless the user opts in. If the user already has dedicated App Store Connect agent skills installed (for example rorkai/app-store-connect-cli-skills via the standard skills installer), defer to those flows instead of duplicating them. From 51607a8687a1b51fb814f4f96efa13736433ce9e Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:08:51 -0700 Subject: [PATCH 08/13] chore(gstack2): regenerate Apple release adapter Co-Authored-By: Claude Fable 5 --- skills/ship/references/APPLE-RELEASE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/skills/ship/references/APPLE-RELEASE.md b/skills/ship/references/APPLE-RELEASE.md index 17e8a483ff..60a28de6d9 100644 --- a/skills/ship/references/APPLE-RELEASE.md +++ b/skills/ship/references/APPLE-RELEASE.md @@ -28,6 +28,15 @@ Resolve and verify before archiving. Fix what the printed mutation boundary auth 3. Authenticate with an App Store Connect API key (`-authenticationKeyPath`, `-authenticationKeyID`, `-authenticationKeyIssuerID`). The `.p8` key is a secret under the `THIRD-PARTY-ACTIONS.md` rules: stored outside the repository, referenced by path, never echoed. 4. The upload is an external effect: run it through the durable state wrapper with a key like `appstore.upload..`. Never re-upload on ambiguity; inspect App Store Connect for the build first. +## Store assets + +When preflight finds a missing icon, or the storefront step needs screenshots, ask the user first — one question, then act on their choice. Never generate marketing assets or spend the user's image-API budget unprompted. Offer: + +- **App icon**: SnapAI (`npx snapai`, the app-icon agent skill) generates a 1024×1024 icon-styled square with the user's own OpenAI key (roughly $0.05–0.19 per icon); Xcode 15+ derives every size from that single image, so no resizer tool is needed. +- **Marketing screenshots**: the aso-appstore-screenshots agent skill (benefit-headline discovery, deterministic scaffold, Nano Banana Pro enhancement with the user's Gemini key, exact App Store dimensions). If installed, follow its workflow rather than reimplementing it. +- **Plain device framing**: `asc screenshots capture` and `asc screenshots frame` — free, local, upload-normalized output (requires the axe CLI and pinned Koubou). +- **User-supplied assets**: always a valid answer; validate dimensions and move on. + ## App Store Connect completion The App Store Connect API covers nearly all remaining work; drive it from a CLI, not a browser. Offer to install a dedicated App Store Connect CLI with one explicit consent question: `asc` (rorkai/App-Store-Connect-CLI, `brew install asc`) is the default offer; ittybittyapps/appstoreconnect-cli and codemagic-ci-cd cli-tools are equivalents if the user prefers them. It is a machine-level tool authenticated with the same App Store Connect API key, never a project dependency, and its telemetry is disabled unless the user opts in. If the user already has dedicated App Store Connect agent skills installed (for example rorkai/app-store-connect-cli-skills via the standard skills installer), defer to those flows instead of duplicating them. From 43f6990866def1c9303502e294ede54da788d8e3 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:08:51 -0700 Subject: [PATCH 09/13] docs: CHANGELOG 1.64.0.0 adds store-asset offer bullet Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 120ff6b9f9..26224930f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ The distance between "my app works in the simulator" and "my app is in review" u - `references/APPLE-RELEASE.md` generated into the ship tree: paid Apple Developer Program membership gate with honest free-account ceilings, native-toolchain release preflight, archive/validate/upload via `xcodebuild` with App Store Connect API key auth, uploads and submissions bound to the durable external-effects wrapper, and App Store Connect completion (metadata, screenshots, TestFlight, Submit for Review, status monitoring) driven by a consent-gated App Store Connect API CLI (`asc` by default, ittybittyapps and Codemagic equivalents named). Browser/manual fallback only for what the API cannot do: initial app record, agreements, banking/tax. - Ship dispatch protocol step 10: Apple platform targets load the adapter before release preparation. +- Store-asset offers, asked before any generation: SnapAI app icons (one 1024×1024 image, Xcode derives the rest), ASO marketing screenshots via the aso-appstore-screenshots skill, free local device framing via `asc screenshots frame`, or bring your own. The skill never spends your image-API budget without asking. ### For contributors From f352aab1a2b1969d40ec6afe1c998bb3efa6730c Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:17:51 -0700 Subject: [PATCH 10/13] feat(gstack2): add free deck-editor option to store-asset offers Co-Authored-By: Claude Fable 5 --- scripts/gstack2/generate-skill-tree.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index c0e3246532..b3a72363ad 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -674,6 +674,7 @@ When preflight finds a missing icon, or the storefront step needs screenshots, a - **App icon**: SnapAI (\`npx snapai\`, the app-icon agent skill) generates a 1024×1024 icon-styled square with the user's own OpenAI key (roughly $0.05–0.19 per icon); Xcode 15+ derives every size from that single image, so no resizer tool is needed. - **Marketing screenshots**: the aso-appstore-screenshots agent skill (benefit-headline discovery, deterministic scaffold, Nano Banana Pro enhancement with the user's Gemini key, exact App Store dimensions). If installed, follow its workflow rather than reimplementing it. - **Plain device framing**: \`asc screenshots capture\` and \`asc screenshots frame\` — free, local, upload-normalized output (requires the axe CLI and pinned Koubou). +- **Designed screenshot decks, free and local**: the app-store-screenshots agent skill (parthjadhav editor) — scaffold its editor, prefill \`app-store-screenshots.json\` with captures and copy, and export one bundle covering every required iPhone size per locale; the user can refine slides interactively before export. - **User-supplied assets**: always a valid answer; validate dimensions and move on. ## App Store Connect completion From 822fddec3600eb72c17f176f2d0e9a4e5c01a68b Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:17:51 -0700 Subject: [PATCH 11/13] chore(gstack2): regenerate Apple release adapter Co-Authored-By: Claude Fable 5 --- skills/ship/references/APPLE-RELEASE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/skills/ship/references/APPLE-RELEASE.md b/skills/ship/references/APPLE-RELEASE.md index 60a28de6d9..4262bbdfa4 100644 --- a/skills/ship/references/APPLE-RELEASE.md +++ b/skills/ship/references/APPLE-RELEASE.md @@ -35,6 +35,7 @@ When preflight finds a missing icon, or the storefront step needs screenshots, a - **App icon**: SnapAI (`npx snapai`, the app-icon agent skill) generates a 1024×1024 icon-styled square with the user's own OpenAI key (roughly $0.05–0.19 per icon); Xcode 15+ derives every size from that single image, so no resizer tool is needed. - **Marketing screenshots**: the aso-appstore-screenshots agent skill (benefit-headline discovery, deterministic scaffold, Nano Banana Pro enhancement with the user's Gemini key, exact App Store dimensions). If installed, follow its workflow rather than reimplementing it. - **Plain device framing**: `asc screenshots capture` and `asc screenshots frame` — free, local, upload-normalized output (requires the axe CLI and pinned Koubou). +- **Designed screenshot decks, free and local**: the app-store-screenshots agent skill (parthjadhav editor) — scaffold its editor, prefill `app-store-screenshots.json` with captures and copy, and export one bundle covering every required iPhone size per locale; the user can refine slides interactively before export. - **User-supplied assets**: always a valid answer; validate dimensions and move on. ## App Store Connect completion From 8ca73f976b858703a9a30d0f68bdd88bc2c2214b Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:17:51 -0700 Subject: [PATCH 12/13] docs: CHANGELOG 1.64.0.0 store-asset bullet includes deck editor Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26224930f4..2ffee89ab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ The distance between "my app works in the simulator" and "my app is in review" u - `references/APPLE-RELEASE.md` generated into the ship tree: paid Apple Developer Program membership gate with honest free-account ceilings, native-toolchain release preflight, archive/validate/upload via `xcodebuild` with App Store Connect API key auth, uploads and submissions bound to the durable external-effects wrapper, and App Store Connect completion (metadata, screenshots, TestFlight, Submit for Review, status monitoring) driven by a consent-gated App Store Connect API CLI (`asc` by default, ittybittyapps and Codemagic equivalents named). Browser/manual fallback only for what the API cannot do: initial app record, agreements, banking/tax. - Ship dispatch protocol step 10: Apple platform targets load the adapter before release preparation. -- Store-asset offers, asked before any generation: SnapAI app icons (one 1024×1024 image, Xcode derives the rest), ASO marketing screenshots via the aso-appstore-screenshots skill, free local device framing via `asc screenshots frame`, or bring your own. The skill never spends your image-API budget without asking. +- Store-asset offers, asked before any generation: SnapAI app icons (one 1024×1024 image, Xcode derives the rest), ASO marketing screenshots via the aso-appstore-screenshots skill, free local device framing via `asc screenshots frame`, free multi-size screenshot decks via the app-store-screenshots editor skill, or bring your own. The skill never spends your image-API budget without asking. ### For contributors From 560622dd20d190c15ed67d7f64d615cd6e1a249c Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 15:45:09 -0700 Subject: [PATCH 13/13] fix: sync package.json version with VERSION 1.64.0.0 Co-Authored-By: Claude Fable 5 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d2a2550ed6..2f7339a123 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gstack", - "version": "1.63.0.0", - "description": "GStack 2 — six portable Agent Skills with an optional host-neutral runtime.", + "version": "1.64.0.0", + "description": "GStack 2 \u2014 six portable Agent Skills with an optional host-neutral runtime.", "license": "MIT", "type": "module", "gstack": {