@mmerterden/multi-agent-pipeline 14.1.1 → 14.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/README.md +10 -6
  3. package/README.tr.md +143 -0
  4. package/docs/architecture.md +23 -8
  5. package/docs/ecosystem.md +237 -0
  6. package/install/_plugin-skills.mjs +16 -2
  7. package/install/codex.mjs +9 -4
  8. package/install/templates/copilot-instructions.md +12 -9
  9. package/package.json +1 -1
  10. package/pipeline/commands/deploy.md +4 -1
  11. package/pipeline/commands/multi-agent/SKILL.md +8 -5
  12. package/pipeline/commands/multi-agent/analysis/SKILL.md +2 -2
  13. package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
  14. package/pipeline/commands/multi-agent/channels/SKILL.md +15 -4
  15. package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -4
  16. package/pipeline/commands/multi-agent/dev/SKILL.md +10 -23
  17. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +10 -2
  18. package/pipeline/commands/multi-agent/dev-local/SKILL.md +10 -24
  19. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +10 -3
  20. package/pipeline/commands/multi-agent/help/SKILL.md +49 -11
  21. package/pipeline/commands/multi-agent/jira/SKILL.md +13 -2
  22. package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
  23. package/pipeline/commands/multi-agent/local/SKILL.md +6 -2
  24. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +6 -2
  25. package/pipeline/commands/multi-agent/log/SKILL.md +7 -1
  26. package/pipeline/commands/multi-agent/setup/SKILL.md +1 -1
  27. package/pipeline/commands/multi-agent/ship/SKILL.md +5 -1
  28. package/pipeline/commands/multi-agent/store-ready/SKILL.md +340 -0
  29. package/pipeline/commands/multi-agent/sync/SKILL.md +7 -6
  30. package/pipeline/commands/multi-agent/test/SKILL.md +18 -8
  31. package/pipeline/commands/multi-agent/test-accessibility/SKILL.md +33 -0
  32. package/pipeline/commands/multi-agent/test-dark-mode/SKILL.md +33 -0
  33. package/pipeline/commands/multi-agent/test-dynamic-type/SKILL.md +33 -0
  34. package/pipeline/commands/multi-agent/test-screenshots/SKILL.md +41 -0
  35. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +28 -201
  36. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  37. package/pipeline/commands/sim-test.md +45 -36
  38. package/pipeline/lib/extract-conventions.sh +44 -15
  39. package/pipeline/lib/fetch-figma-annotations.sh +8 -1
  40. package/pipeline/lib/fetch-fortify.sh +23 -8
  41. package/pipeline/lib/figma-screenshot.sh +11 -1
  42. package/pipeline/lib/issue-fetcher.sh +76 -9
  43. package/pipeline/lib/md2confluence-v3.py +16 -2
  44. package/pipeline/lib/plan-todos.sh +5 -2
  45. package/pipeline/lib/post-pr-review.sh +8 -6
  46. package/pipeline/lib/shadow-git.sh +50 -9
  47. package/pipeline/lib/submodule-detector.sh +8 -1
  48. package/pipeline/multi-agent-refs/_input-parser.md +1 -1
  49. package/pipeline/multi-agent-refs/channels/confluence.md +3 -0
  50. package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
  51. package/pipeline/multi-agent-refs/channels/jira.md +13 -2
  52. package/pipeline/multi-agent-refs/channels/pr-review-actions.md +1 -1
  53. package/pipeline/multi-agent-refs/channels/pr.md +20 -0
  54. package/pipeline/multi-agent-refs/channels/wiki.md +1 -1
  55. package/pipeline/multi-agent-refs/cross-cli-contract.md +6 -5
  56. package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
  57. package/pipeline/multi-agent-refs/generate-issue.md +2 -2
  58. package/pipeline/multi-agent-refs/issue-jira-triad.md +3 -3
  59. package/pipeline/multi-agent-refs/knowledge.md +1 -1
  60. package/pipeline/multi-agent-refs/payload-contracts.md +67 -0
  61. package/pipeline/multi-agent-refs/phases/modes.md +20 -0
  62. package/pipeline/multi-agent-refs/phases/phase-0-init.md +2 -2
  63. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -40
  64. package/pipeline/multi-agent-refs/phases/phase-7-report.md +5 -3
  65. package/pipeline/multi-agent-refs/phases.md +6 -0
  66. package/pipeline/multi-agent-refs/rules.md +2 -0
  67. package/pipeline/schemas/prefs.schema.json +2 -2
  68. package/pipeline/scripts/audit-log-rotate.sh +10 -0
  69. package/pipeline/scripts/build-stack-plugins.mjs +8 -1
  70. package/pipeline/scripts/check-derived-drift.mjs +13 -1
  71. package/pipeline/scripts/diff-explain.mjs +41 -3
  72. package/pipeline/scripts/diff-risk-score.mjs +72 -8
  73. package/pipeline/scripts/gen-mode-dispatch.mjs +1 -1
  74. package/pipeline/scripts/learning-curve.mjs +8 -2
  75. package/pipeline/scripts/output-quality-check.sh +15 -4
  76. package/pipeline/scripts/phase-tracker.sh +21 -8
  77. package/pipeline/scripts/pre-commit-check.sh +69 -22
  78. package/pipeline/scripts/render-agent-log-cost.sh +8 -3
  79. package/pipeline/scripts/render-cost-summary.sh +42 -22
  80. package/pipeline/scripts/render-work-summary.sh +47 -13
  81. package/pipeline/scripts/review-scope.mjs +1 -1
  82. package/pipeline/scripts/run-aggregator.mjs +38 -14
  83. package/pipeline/scripts/smoke-schema-validation.sh +5 -1
  84. package/pipeline/scripts/test-gap-scan.mjs +45 -6
  85. package/pipeline/scripts/uninstall.mjs +39 -4
  86. package/pipeline/scripts/update-issue-progress.sh +12 -16
  87. package/pipeline/scripts/worktree-finalize.sh +23 -2
  88. package/pipeline/skills/.skills-index.json +58 -4
  89. package/pipeline/skills/shared/README.md +12 -7
  90. package/pipeline/skills/shared/core/multi-agent/SKILL.md +13 -17
  91. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -0
  92. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  93. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +4 -17
  94. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +8 -0
  95. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +5 -18
  96. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +8 -0
  97. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +50 -12
  98. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
  99. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +4 -0
  100. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +4 -0
  101. package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +18 -3
  102. package/pipeline/skills/shared/core/multi-agent-ship/SKILL.md +4 -0
  103. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +50 -0
  104. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +6 -5
  105. package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +18 -8
  106. package/pipeline/skills/shared/core/multi-agent-test-accessibility/SKILL.md +37 -0
  107. package/pipeline/skills/shared/core/multi-agent-test-dark-mode/SKILL.md +37 -0
  108. package/pipeline/skills/shared/core/multi-agent-test-dynamic-type/SKILL.md +37 -0
  109. package/pipeline/skills/shared/core/multi-agent-test-screenshots/SKILL.md +44 -0
  110. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +29 -101
  111. package/pipeline/skills/shared/external/firebase/SKILL.md +1 -1
  112. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +302 -0
  113. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +144 -0
  114. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +156 -0
  115. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +108 -0
  116. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +175 -0
  117. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +865 -0
  118. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +335 -0
  119. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +344 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +130 -0
  121. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +264 -0
  122. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +298 -0
  123. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +529 -0
  124. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +187 -0
  125. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +171 -0
  126. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +184 -0
  127. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +26 -0
  128. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +173 -0
  129. package/pipeline/skills/skills-index.md +10 -4
@@ -0,0 +1,340 @@
1
+ ---
2
+ description: "Pre-submission store readiness for a built package, iOS and Android, local-only. Three symmetric gates per platform: a static package audit, the store's own authoritative validation, and a policy review against repo source. Separate verdict per gate, a skipped gate never counted as a pass. Validates only, never uploads. Use when a build is about to go to TestFlight or a Play track, or when a submission was rejected and the reason is not obvious."
3
+ description-tr: "Üretilmiş paketin yükleme öncesi store hazırlığı, iOS + Android, yalnızca lokal. Platform başına üç simetrik kapı: statik paket denetimi, store'un kendi doğrulayıcısı, ve kaynağa karşı politika incelemesi. Kapı başına ayrı verdict, atlanan kapı asla pass sayılmaz. Sadece doğrular, asla yüklemez."
4
+ argument-hint: "[repo] - empty = pick; repo name or path; --ipa= | --archive= | --aab= | --apk=; --skip-sweep; --resume"
5
+ allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep, TaskCreate, TaskUpdate, AskUserQuestion, Skill, mcp__dev-toolkit__ios_app_store_audit, mcp__dev-toolkit__ios_export_ipa, mcp__dev-toolkit__ios_testflight_validate, mcp__dev-toolkit__ios_xcodebuild, mcp__dev-toolkit__ios_xcresult, mcp__dev-toolkit__android_apk_audit, mcp__dev-toolkit__ios_screenshot, mcp__dev-toolkit__ios_get_ui_tree, mcp__dev-toolkit__ios_set_appearance, mcp__dev-toolkit__ios_set_content_size, mcp__dev-toolkit__android_screenshot, mcp__dev-toolkit__android_get_ui_tree, mcp__dev-toolkit__android_set_dark_mode, mcp__dev-toolkit__android_set_font_scale
6
+ ---
7
+
8
+ # /multi-agent:store-ready - pre-submission validation, iOS + Android
9
+
10
+ Catch, before you upload, what App Store Connect or the Play Console would send
11
+ back after you do.
12
+
13
+ **Local-only.** No commits, no push, no PR, no channels unless you ask at the end.
14
+ A worktree, when one is needed, exists only to archive without touching your
15
+ working tree.
16
+
17
+ **It never uploads.** iOS runs `--validate-app`, never `--upload-app`. Android
18
+ never commits a Play edit. A validation run must not be able to ship a build by
19
+ accident.
20
+
21
+ **Input**: $ARGUMENTS
22
+
23
+ ## Why three gates, and why the same three on both platforms
24
+
25
+ Each gate sees something the others structurally cannot, and reporting one of them
26
+ as "the check" is how a build passes locally and gets rejected anyway. The shapes
27
+ are the same on iOS and Android because the failure modes are: a malformed package,
28
+ a package the store itself refuses, and a policy a human enforces.
29
+
30
+ | Gate | Sees | Blind to |
31
+ |---|---|---|
32
+ | **1. Static** | package structure, manifests, signing, declared APIs and SDKs | anything depending on the store account |
33
+ | **2. Authoritative** | what the store's own validator says about this exact binary | written policy - no validator reads it |
34
+ | **3. Policy** | consent flows, deletion paths, purchase routing, disclosures | anything not visible in source |
35
+
36
+ ### Gate matrix
37
+
38
+ | Gate | iOS | Android |
39
+ |---|---|---|
40
+ | 1 Static | `ios_app_store_audit({archive_path, rules: "all"})` - 18 rules with real ITMS codes. Needs an `.xcarchive`. Reference: `apple-archive-compliance` skill | `android_apk_audit` plus the `google-play-compliance` skill's 21 rules: `bundletool validate` + manifest dump, `aapt2 dump badging`, `apksigner verify`, ABI / native scan. Needs an `.aab` (an `.apk` narrows it, see Step 3) |
41
+ | 2 Authoritative | `ios_testflight_validate({ipa_path, platform: "ios", <credentials>})` → `xcrun altool --validate-app`. Needs an `.ipa` + credentials | **No client shipped.** Play's authoritative check exists only server-side, through a Publishing API draft edit that is validated and then abandoned. The pipeline has no tool for it, so this gate reports `SKIPPED (no local Play validator)` and the report says so. Do not substitute `bundletool validate` - that is Gate 1 |
42
+ | 3 Policy | `app-store-review` skill vs repo source | `play-store-review` skill vs repo source |
43
+
44
+ Gate 2's asymmetry is real and is reported as an asymmetry, not smoothed over. On
45
+ iOS it is the only gate that catches a version+build pair already used - the most
46
+ common wasted upload. On Android nothing local reproduces it, so an Android run
47
+ clears at most 2 of 3 gates and must never print `passed`.
48
+
49
+ ## Step 0 - parse input, detect platform
50
+
51
+ | Input | Meaning |
52
+ |---|---|
53
+ | (empty) | ask which repo (Step 1) |
54
+ | `my-app` or a path | that repo |
55
+ | `--archive=<path>` | iOS, build supplied; all three gates can run |
56
+ | `--ipa=<path>` | iOS, build supplied; Gate 1 reports `SKIPPED (needs .xcarchive)` |
57
+ | `--aab=<path>` | Android, build supplied; Gate 1 + 3 run |
58
+ | `--apk=<path>` | Android; Gate 1 runs the subset that does not need a bundle, and says which rules it could not apply |
59
+ | `--skip-sweep` | skip Step A, when no simulator / emulator is available or only the package matters |
60
+ | `--resume` | continue the last run from its state file |
61
+
62
+ Platform detection when no build flag is given:
63
+
64
+ ```
65
+ cwd or repo contains .xcodeproj / .xcworkspace / Package.swift -> iOS
66
+ cwd or repo contains build.gradle / build.gradle.kts -> Android
67
+ both -> ask which
68
+ neither -> halt: "store-ready needs an iOS or Android project"
69
+ ```
70
+
71
+ State lives at `$HOME/.claude/logs/multi-agent/<task_id>/agent-state.json` with
72
+ `taskId = SR-<repo>-<yyyymmddHHMM>`. Register phases with the tracker
73
+ (`$HOME/.claude/multi-agent-refs/tracker-contract.md`) so `:resume` and `:status`
74
+ work like any other run.
75
+
76
+ ## Step 1 - pickers (native, always)
77
+
78
+ Use `AskUserQuestion` for every step - never a numbered text menu. Questions and
79
+ descriptions render in `prefs.global.outputLanguage`; `label` and `header` stay
80
+ English, per `$HOME/.claude/multi-agent-refs/picker-contract.md`. Print the
81
+ `Step <i>/<n>: <what this decides>` breadcrumb for each.
82
+
83
+ 1. **Repo** - from `prefs.projects` matching the detected platform. A single match
84
+ auto-resolves (say so in the breadcrumb, do not silently skip the step).
85
+ 2. **Branch** - the branch to validate. Resolution order:
86
+ - `git fetch --prune` first, capturing **stderr**. **If the fetch fails, do not
87
+ silently fall back to a cached ref**, and **classify before naming a cause** -
88
+ the same rule as the `/multi-agent:dev` remote gate:
89
+
90
+ | stderr contains | Cause | Remedy |
91
+ |---|---|---|
92
+ | `could not read Password`, `Authentication failed`, `403` | credential | store the PAT in the credential helper or switch the remote to SSH. **A VPN cannot fix this**, and the base ref being stale is unrelated to what broke - do not offer the cached-ref fallback. |
93
+ | `Could not resolve host`, `Operation timed out`, `Connection refused` | network | retry / continue on the cached ref with an explicit warning / switch remote / abort, per `$HOME/.claude/multi-agent-refs/rules.md` |
94
+ | `Repository not found`, `404` | wrong remote | show `git remote -v` and ask |
95
+
96
+ Always print the observed stderr line next to the classification. Asserting
97
+ `unreachable (VPN/DNS)` for a missing-credential error that returns in under a
98
+ second sends the user to fix something that was never broken.
99
+ - Offer the current branch, the default branch, and any `release/*` /
100
+ `tkdevelop/*` heads.
101
+ 3. **Mode** - how the build is obtained:
102
+ - `Supply a build` (Mode B, default) - fastest, no signing needed in-run.
103
+ - `Build from this branch` (Mode A) - iOS needs a distribution certificate and
104
+ profile in the keychain; Android needs the release signing config. Takes as
105
+ long as a real release build.
106
+
107
+ ## Step 2 - pre-flight, before anything expensive
108
+
109
+ Report every line; a missing prerequisite is a halt, not a warning.
110
+
111
+ **iOS:**
112
+
113
+ ```bash
114
+ xcrun --find altool >/dev/null 2>&1 || echo "MISSING: altool (install Xcode)"
115
+ xcodebuild -version | head -1
116
+ ```
117
+
118
+ Then resolve credentials, and **state which tier is active in the report**:
119
+
120
+ | Tier | Source | Effect |
121
+ |---|---|---|
122
+ | 1 | ASC API key - key id + issuer id from the keychain via `prefs.global.keychainMapping`, `.p8` at `~/.appstoreconnect/private_keys/AuthKey_<keyId>.p8` | Gate 2 runs |
123
+ | 2 | Apple ID + app-specific password, referenced as a keychain item | Gate 2 runs |
124
+ | 3 | neither | **Gate 2 reports `SKIPPED`, and the run says so in the verdict line** |
125
+
126
+ Multi-provider accounts need `--provider-public-id`. When it is not in prefs, run
127
+ `ios_testflight_validate({list_providers: true})` once and ask which provider.
128
+
129
+ **Android:**
130
+
131
+ ```bash
132
+ command -v bundletool >/dev/null || echo "MISSING: bundletool"
133
+ command -v aapt2 >/dev/null || echo "MISSING: aapt2 (Android SDK build-tools)"
134
+ command -v apksigner >/dev/null || echo "MISSING: apksigner (Android SDK build-tools)"
135
+ ```
136
+
137
+ There is no credential tier to resolve: Gate 2 has no local client, so it is
138
+ `SKIPPED` by construction rather than by configuration. Say which of the two it is
139
+ - a user who thinks a credential would unlock it will go looking for one.
140
+
141
+ Credentials come from `/multi-agent:setup`; never prompt for a secret value in
142
+ chat.
143
+
144
+ ## Step A - running-app sweep (unless `--skip-sweep`)
145
+
146
+ The gates read a package; this reads the app. A build can be structurally perfect
147
+ and still ship an unreadable screen, so the sweep stays part of store readiness
148
+ rather than being a separate errand.
149
+
150
+ Requires a booted simulator / emulator. When none is available, report
151
+ `Sweep: SKIPPED (no booted device)` and continue to the gates - never halt the
152
+ package validation for it, and never silently omit the line.
153
+
154
+ Delegate to the UI Bug Hunter flow (`$HOME/.claude/commands/sim-test.md`) for the
155
+ mechanics, running the light + dark + large-text passes over every screen. Merge
156
+ its findings into the single report at Step 7, severity-grouped alongside the gate
157
+ findings.
158
+
159
+ ## Step 3 - obtain the build
160
+
161
+ ### Mode B - a build you supply
162
+
163
+ - **iOS `.xcarchive`** → Gate 1 runs on it. To reach Gate 2 the archive must be
164
+ exported, so run `ios_export_ipa` (see Mode A for the signing inputs).
165
+ - **iOS `.ipa` only** → **Gate 1 is `SKIPPED (needs .xcarchive)`.** The static audit
166
+ reads archive structure an `.ipa` does not carry. Do not present a two-gate run as
167
+ a full pass; say which gate did not run and why, and offer to re-run with the
168
+ archive.
169
+ - **Android `.aab`** → Gate 1 runs in full.
170
+ - **Android `.apk` only** → Gate 1 runs the rules that do not need a bundle and
171
+ **lists the rules it could not apply**. An `.apk` cannot answer bundle-level
172
+ questions (per-ABI splits, dynamic features, Play App Signing expectations).
173
+
174
+ When no path is given, pick the newest artifact and print which one you picked:
175
+
176
+ ```
177
+ iOS: newest .xcarchive under ~/Library/Developer/Xcode/Archives/**
178
+ Android: newest .aab under **/build/outputs/bundle/**/*.aab
179
+ ```
180
+
181
+ Never validate an artifact whose provenance you did not state. "The newest archive"
182
+ is a guess the user must be able to correct.
183
+
184
+ ### Mode A - build from the branch
185
+
186
+ 1. Worktree at `{projectRoot}/{worktreeBasePath}/{taskId}` on the chosen branch.
187
+ **Never under `$HOME`**, never a direct checkout of the main working tree.
188
+ 2. Resolve the scheme / module and workspace / project from prefs; ask if ambiguous.
189
+ 3. Build:
190
+ - **iOS**: `ios_xcodebuild({workspace|project, scheme, action: "archive", configuration: "Release", destination: "generic/platform=iOS"})`.
191
+ Note the destination: the simulator default would produce an archive that
192
+ cannot be exported for distribution.
193
+ - **Android**: `./gradlew bundleRelease` (or the release variant the module
194
+ declares). A debug-signed bundle fails Gate 1 signing rules for the wrong
195
+ reason - if no release signing config resolves, halt and say so rather than
196
+ auditing a debug artifact.
197
+ 4. **iOS export**:
198
+ `ios_export_ipa({archive_path, output_dir, method: "app-store-connect", team_id, provisioning_profiles?, signing_style?})`.
199
+ Leave `allow_provisioning_updates` off unless the user asks: it lets xcodebuild
200
+ create or modify profiles in the developer account, which a validation run has no
201
+ business doing.
202
+ 5. A failed build or export halts with the parsed errors. The usual iOS causes are a
203
+ missing distribution certificate, a profile that does not match the bundle ID, or
204
+ `signing_style: "manual"` with no `provisioning_profiles` map.
205
+
206
+ ## Step 4 - Gate 1, static package audit
207
+
208
+ - **iOS**: `ios_app_store_audit({archive_path, rules: "all"})`. Consult the
209
+ `apple-archive-compliance` skill for what each rule means.
210
+
211
+ Needs `@mmerterden/dev-toolkit-mcp` ≥ v2.9.0, which provides the tool. When the
212
+ MCP server is not registered, the same 18 rules run directly from the package:
213
+
214
+ ```bash
215
+ node -e "import('@mmerterden/dev-toolkit-mcp/tools/ios-app-store-audit/index.js').then(m => m.runAudit({ archivePath: '<path>', rules: 'all' }).then(r => console.log(JSON.stringify(r))))"
216
+ ```
217
+
218
+ Use the fallback only when the tool is genuinely absent, and say in the report
219
+ which path ran - a rule set that silently differed between two invocations is
220
+ worse than a missing gate.
221
+ - **Android**: `android_apk_audit` on the artifact, plus the
222
+ `google-play-compliance` skill's 21 rules - `bundletool validate` and manifest
223
+ dump, `aapt2 dump badging`, `apksigner verify`, ABI / native scan.
224
+
225
+ `error` findings are blocking; `warning` is advisory. Group by severity and keep
226
+ each finding's ITMS / Play policy code - Gate 2 may return the same code on iOS,
227
+ and seeing it in both places tells the user it is real rather than a heuristic.
228
+
229
+ ## Step 5 - Gate 2, the store's own validation
230
+
231
+ **iOS**: `ios_testflight_validate({ipa_path, platform: "ios", <credential args>})`.
232
+ Render the verdict exactly as returned:
233
+
234
+ - `PASS` - Apple accepted the binary for delivery.
235
+ - `FAIL` - list each issue with its ITMS code, the mapped guideline, and the hint.
236
+ - `SKIPPED` - print the reason. **Never render this as a pass.**
237
+
238
+ Gate 2 is the only gate that catches a build number already used - so when it
239
+ fails on that, say so plainly and name the next free build number.
240
+
241
+ **Android**: report `SKIPPED (no local Play validator)` with one line on why: the
242
+ authoritative check is a Play Publishing API draft edit, the pipeline ships no
243
+ client for it, and no local tool substitutes. `bundletool validate` is Gate 1 and
244
+ reporting it here would fake a cleared gate.
245
+
246
+ ## Step 6 - Gate 3, policy review
247
+
248
+ Load the platform's review skill and review the repo against it. This is the gate
249
+ that catches what a human reviewer rejects, so it reads source, not the binary.
250
+
251
+ **iOS** - `app-store-review`:
252
+
253
+ | Area | Evidence to gather |
254
+ |---|---|
255
+ | Purpose strings | every `NS*UsageDescription` in Info.plist - present, specific, user-facing, and matching what the code actually does with the data |
256
+ | Privacy manifest | `PrivacyInfo.xcprivacy` exists, declares required-reason APIs, and matches the SDKs actually linked |
257
+ | Tracking | if any tracking API or SDK is present, an ATT prompt exists and runs before collection |
258
+ | Account deletion | if the app creates accounts, an in-app deletion path exists (guideline 5.1.1(v)) |
259
+ | Privacy policy | reachable in-app and in the metadata |
260
+ | IAP | anything unlocking features goes through StoreKit, with no external purchase path |
261
+ | Sign in with Apple | present when a third-party social login is offered |
262
+
263
+ **Android** - `play-store-review`:
264
+
265
+ | Area | Evidence to gather |
266
+ |---|---|
267
+ | Permissions | every `uses-permission` justified by a feature, no sensitive permission without its declaration form |
268
+ | Data safety | the declared data-safety answers match what the code collects and transmits |
269
+ | Target API level | meets the current Play requirement for new releases |
270
+ | Privacy policy | reachable in-app and in the listing |
271
+ | Billing | anything unlocking features goes through Play Billing, with no external purchase path |
272
+ | Account deletion | if the app creates accounts, an in-app deletion path exists, plus the web deletion URL Play requires |
273
+ | Content rating | the questionnaire answers match the app's actual content |
274
+ | Signing | Play App Signing configured, upload key distinct from the app signing key |
275
+
276
+ For each: `pass` / `fail` / `not-applicable` with the evidence path that justifies
277
+ it. `not-applicable` needs a reason - an unexamined area is not a pass.
278
+
279
+ ## Step 7 - report
280
+
281
+ Write to `~/StoreChecks/<platform>-<repo>-<branch>-<timestamp>/report.md` and print
282
+ a summary.
283
+
284
+ ```
285
+ Verdict: <N> of 3 gates cleared[, <M> skipped]
286
+ Platform:<ios|android>
287
+ Build: <artifact path> · <bundle id / applicationId> <version> (<build>)
288
+ Auth: tier <1|2|none> · <method> (iOS only)
289
+ Sweep: <n> findings | SKIPPED (<reason>)
290
+
291
+ Gate 1 static audit PASS | FAIL (<n> blocking, <n> advisory) | SKIPPED (<reason>)
292
+ Gate 2 store validation PASS | FAIL (<n> issues) | SKIPPED (<reason>)
293
+ Gate 3 policy review PASS | FAIL (<n> findings) | <n> not-applicable
294
+
295
+ Blocking - fix before uploading
296
+ [ITMS-90683] Info.plist: NSCameraUsageDescription missing
297
+ guideline 5.1.1 Data Collection and Storage
298
+ <hint>
299
+ <file:line>
300
+
301
+ Advisory
302
+ ...
303
+
304
+ Not run
305
+ Gate 2: no local Play validator - authoritative check is server-side only
306
+ ```
307
+
308
+ Rules for the report:
309
+
310
+ - A skipped gate is never folded into the pass count. The verdict line states the
311
+ skip. An Android run therefore reads `2 of 3 gates cleared, 1 skipped` at best.
312
+ - Every blocking finding carries a file path or a store code. A finding the user
313
+ cannot act on is noise.
314
+ - Humanize via `--lang en` by default (`promptLanguage` is locked to `"en"`); pass
315
+ `--lang=tr` explicitly to opt into Turkish.
316
+ - No AI or assistant attribution anywhere, per
317
+ `$HOME/.claude/rules/git-conventions.md`.
318
+ - Real newlines, no HTML entities, per
319
+ `$HOME/.claude/multi-agent-refs/rules.md "External System Outputs"`.
320
+
321
+ ## Step 8 - offer the next action, do not take it
322
+
323
+ Print, and stop:
324
+
325
+ - the exact upload command for when the gates are clear, so uploading stays an
326
+ explicit human act:
327
+ - iOS: `xcrun altool --upload-app ...`
328
+ - Android: the Play Console upload, or the `gradle publish` task the project
329
+ declares - never run it
330
+ - `/multi-agent:store-ready --resume` to re-run after fixes
331
+ - `/multi-agent:channels` to land the findings in Jira / Confluence / Wiki / PR
332
+ - `/multi-agent:fix-bug` when Gate 3 produced code-level findings
333
+
334
+ Never upload, never commit a Play edit, never bump the build number, never commit.
335
+
336
+ ## Related surfaces
337
+
338
+ `/multi-agent:testflight-validation` is a thin alias onto this command, kept so the
339
+ iOS-only name keeps working; it resolves here with the platform pinned to iOS.
340
+ `/multi-agent:test "store-ready"` also resolves here. There is one implementation.
@@ -59,8 +59,8 @@ Run every step automatically:
59
59
  ```
60
60
  Step 1: PLATFORM Detect macOS / Linux / Windows (Git Bash / WSL); export PLATFORM env
61
61
  Step 1.5: DETECT Compare timestamps, find stale targets
62
- Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 44 sub-command skills)
63
- Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 44 specs as refs + 8 agent TOML)
62
+ Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 49 sub-command skills)
63
+ Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 49 specs as refs + 8 agent TOML)
64
64
  Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
65
65
  Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
66
66
  bump changed plugins' patch version, commit + push the plugins repo)
@@ -176,7 +176,7 @@ If nothing is stale → report "All targets up to date" and stop.
176
176
  Unlike the Copilot step, this one does **not** hand-copy files. The Codex tree is a
177
177
  *transform* of the Claude tree, not a mirror of it, and the transform is real work:
178
178
 
179
- - the 43 sub-command specs become reference files, because Codex silently truncates
179
+ - the 49 sub-command specs become reference files, because Codex silently truncates
180
180
  its skills block (see `cross-cli-contract.md` 2.6 for the measurement)
181
181
  - every `$HOME/.claude/...` reference to a CLI-owned tree is retargeted, with
182
182
  `agents/<persona>.md` becoming `.toml` and the dispatcher becoming the router skill
@@ -484,21 +484,22 @@ When invoked with the `release` argument:
484
484
  > Codex takes the Step 2b path instead; see that section.
485
485
 
486
486
  This runs on the Claude <-> Copilot axis. Codex is NOT synced here: it receives the
487
- same 43 specs as reference files rather than as peer skills, via Step 2b - see
487
+ same 49 specs as reference files rather than as peer skills, via Step 2b - see
488
488
  `cross-cli-contract.md` 2.6 for why the parity axis differs per host.
489
489
 
490
490
  | Claude Code | Copilot CLI |
491
491
  |-------------|-------------|
492
492
  | `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
493
493
 
494
- **44 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
494
+ **49 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
495
495
 
496
496
  ```
497
497
  analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, design-check, dev,
498
498
  dev-autopilot, dev-local, dev-local-autopilot, diff-explain, forget, garbage-collect,
499
499
  help, ios-coding-standard, issue, jira, kill, language, local,
500
500
  local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
501
- routines, save, scan, search, setup, ship, stack, status, sync, test, testflight-validation, uninstall, update
501
+ routines, save, scan, search, setup, ship, stack, status, store-ready, sync, test, test-accessibility,
502
+ test-dark-mode, test-dynamic-type, test-screenshots, testflight-validation, uninstall, update
502
503
  ```
503
504
 
504
505
  **NOT synced**: `$HOME/.claude/multi-agent-refs/*` - lazy-load references, Claude Code specific
@@ -22,14 +22,24 @@ Pass `$ARGUMENTS` through verbatim - sim-test.md decides which test matrix to
22
22
 
23
23
  ## Quick reference
24
24
 
25
- | Invocation | What it does |
26
- |---|---|
27
- | `/multi-agent:test` | Walk every screen, collect screenshots + UI tree, produce a general report |
28
- | `/multi-agent:test "dark mode"` | Light vs dark comparison, contrast + colour bugs |
29
- | `/multi-agent:test "accessibility"` | VoiceOver label + tap-target + contrast audit |
30
- | `/multi-agent:test "dynamic type"` | Layout check at XL-XXXL text sizes |
31
- | `/multi-agent:test "screenshot tr"` | App Store screenshot set (Turkish locale) |
32
- | `/multi-agent:test "store-ready"` | App Store guideline pre-flight check |
25
+ | Invocation | Fixed-scenario alias | What it does |
26
+ |---|---|---|
27
+ | `/multi-agent:test` | - | Walk every screen, collect screenshots + UI tree, produce a general report |
28
+ | `/multi-agent:test "dark mode"` | `/multi-agent:test-dark-mode` | Light vs dark comparison, contrast + colour bugs |
29
+ | `/multi-agent:test "accessibility"` | `/multi-agent:test-accessibility` | VoiceOver label + tap-target + contrast audit |
30
+ | `/multi-agent:test "dynamic type"` | `/multi-agent:test-dynamic-type` | Layout check at XL-XXXL text sizes |
31
+ | `/multi-agent:test "screenshot <lang>"` | `/multi-agent:test-screenshots [locale]` | App Store screenshot set in a locale (alias defaults to tr) |
32
+ | `/multi-agent:test "store-ready" [path]` | hands off to `/multi-agent:store-ready` | package validation, not a UI test |
33
+
34
+ Both columns are supported and neither is deprecated; the aliases exist so the
35
+ scenario list autocompletes off `test-` instead of having to be remembered.
36
+
37
+ `store-ready` is the odd one out: it validates a built **package** rather than a
38
+ running app, so it is not implemented here at all. `/multi-agent:store-ready` owns
39
+ it on both platforms - three gates per platform, plus this file's sweep as its
40
+ Step A. `/multi-agent:testflight-validation` is the iOS-pinned alias of that
41
+ command. The quoted tag is kept as a hand-off so an existing invocation still lands
42
+ somewhere correct.
33
43
 
34
44
  ## Requirements
35
45
 
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: "Accessibility audit on a booted simulator / emulator: VoiceOver labels, sub-44pt tap targets, contrast, traits. Alias pinning the accessibility scenario. Use when auditing a screen for assistive-technology support."
3
+ description-tr: "Booted simulator / emulator üzerinde erişilebilirlik denetimi: VoiceOver label'ları, 44x44pt altı tap target'lar, kontrast oranları ve trait'ler; her ekranda canlı UI tree'ye karşı denetlenir. /multi-agent:test \"accessibility\" için sabit-senaryo alias'ı."
4
+ argument-hint: "(argümansız - senaryo sabit)"
5
+ ---
6
+
7
+ # /multi-agent:test-accessibility - Accessibility audit
8
+
9
+ Fixed-scenario alias. The implementation is the UI Bug Hunter flow; this command
10
+ only pins the scenario so the tag does not have to be typed or quoted.
11
+
12
+ ## Dispatcher
13
+
14
+ Read this file and apply its instructions:
15
+
16
+ ```
17
+ $HOME/.claude/commands/sim-test.md
18
+ ```
19
+
20
+ Run it with **scenario = `accessibility`**. Ignore `$ARGUMENTS`; the scenario is
21
+ fixed by the command name. Anything the user adds is context for the report, never
22
+ a scenario override - to run a different matrix they invoke that command.
23
+
24
+ ## Equivalent
25
+
26
+ `/multi-agent:test "accessibility"` - identical behaviour. Both forms are
27
+ supported; neither is deprecated.
28
+
29
+ ## Requirements
30
+
31
+ - **iOS**: Xcode + a booted Simulator (`xcrun simctl list | grep Booted`)
32
+ - **Android**: Android SDK + a running emulator or USB device (`adb devices`)
33
+ - **MCP**: the `dev-toolkit` MCP server must be installed (tool names start with `mcp__dev-toolkit__`)
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: "Dark mode UI test on a booted simulator / emulator: walk every screen light then dark, report contrast + colour bugs. Alias pinning the dark-mode scenario. Use when a dark-mode rendering bug is suspected."
3
+ description-tr: "Booted simulator / emulator üzerinde dark mode UI testi. Her ekranı light'ta gezer, görünümü değiştirir, tekrar gezer; farktan kontrast + renk + sabit-palet buglarını raporlar. /multi-agent:test \"dark mode\" için sabit-senaryo alias'ı."
4
+ argument-hint: "(argümansız - senaryo sabit)"
5
+ ---
6
+
7
+ # /multi-agent:test-dark-mode - Dark mode UI test
8
+
9
+ Fixed-scenario alias. The implementation is the UI Bug Hunter flow; this command
10
+ only pins the scenario so the tag does not have to be typed or quoted.
11
+
12
+ ## Dispatcher
13
+
14
+ Read this file and apply its instructions:
15
+
16
+ ```
17
+ $HOME/.claude/commands/sim-test.md
18
+ ```
19
+
20
+ Run it with **scenario = `dark mode`**. Ignore `$ARGUMENTS`; the scenario is fixed
21
+ by the command name. Anything the user adds is context for the report, never a
22
+ scenario override - to run a different matrix they invoke that command.
23
+
24
+ ## Equivalent
25
+
26
+ `/multi-agent:test "dark mode"` - identical behaviour. Both forms are supported;
27
+ neither is deprecated.
28
+
29
+ ## Requirements
30
+
31
+ - **iOS**: Xcode + a booted Simulator (`xcrun simctl list | grep Booted`)
32
+ - **Android**: Android SDK + a running emulator or USB device (`adb devices`)
33
+ - **MCP**: the `dev-toolkit` MCP server must be installed (tool names start with `mcp__dev-toolkit__`)
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: "Dynamic Type layout test on a booted simulator / emulator: re-walk every screen at XL through accessibility-extra-large, report truncation and clipping. Alias pinning the dynamic-type scenario. Use when checking a layout survives large text."
3
+ description-tr: "Booted simulator / emulator üzerinde Dynamic Type layout testi. Her ekranı XL'den accessibility-extra-large'a kadar yeniden gezer; kırpılma, taşma, üst üste binme ve ölçeklenmeyi bırakan sabit yükseklikli container'ları raporlar. /multi-agent:test \"dynamic type\" için sabit-senaryo alias'ı."
4
+ argument-hint: "(argümansız - senaryo sabit)"
5
+ ---
6
+
7
+ # /multi-agent:test-dynamic-type - Dynamic Type layout test
8
+
9
+ Fixed-scenario alias. The implementation is the UI Bug Hunter flow; this command
10
+ only pins the scenario so the tag does not have to be typed or quoted.
11
+
12
+ ## Dispatcher
13
+
14
+ Read this file and apply its instructions:
15
+
16
+ ```
17
+ $HOME/.claude/commands/sim-test.md
18
+ ```
19
+
20
+ Run it with **scenario = `dynamic type`**. Ignore `$ARGUMENTS`; the scenario is
21
+ fixed by the command name. Anything the user adds is context for the report, never
22
+ a scenario override - to run a different matrix they invoke that command.
23
+
24
+ ## Equivalent
25
+
26
+ `/multi-agent:test "dynamic type"` - identical behaviour. Both forms are
27
+ supported; neither is deprecated.
28
+
29
+ ## Requirements
30
+
31
+ - **iOS**: Xcode + a booted Simulator (`xcrun simctl list | grep Booted`)
32
+ - **Android**: Android SDK + a running emulator or USB device (`adb devices`)
33
+ - **MCP**: the `dev-toolkit` MCP server must be installed (tool names start with `mcp__dev-toolkit__`)
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: "App Store screenshot set from a booted simulator / emulator in a given locale, taken as an argument and defaulting to tr. Alias pinning the screenshot scenario. Use when generating store screenshots or checking a localised build renders."
3
+ description-tr: "Booted simulator / emulator'dan belirtilen dilde App Store screenshot seti: temiz status bar, her ekran gezilip yakalanır. Dili isim içine gömmek yerine argüman olarak alır (default tr). /multi-agent:test \"screenshot <lang>\" için sabit-senaryo alias'ı."
4
+ argument-hint: "[locale] - boş = tr; örn. tr | en | de | ar"
5
+ ---
6
+
7
+ # /multi-agent:test-screenshots - Locale screenshot set
8
+
9
+ Fixed-scenario alias, **parameterised by locale**. The scenario is pinned; the
10
+ language is not, because one command per language would put a parameter in a name.
11
+
12
+ ## Locale resolution
13
+
14
+ 1. `$ARGUMENTS` names a locale (`tr`, `en`, `de`, `ar`, ...) → use it.
15
+ 2. `$ARGUMENTS` empty → `tr`.
16
+ 3. `$ARGUMENTS` is something other than a locale → do not guess a language and do
17
+ not silently fall back. Ask which locale with `AskUserQuestion`, rendered in
18
+ `outputLanguage`.
19
+
20
+ ## Dispatcher
21
+
22
+ Read this file and apply its instructions:
23
+
24
+ ```
25
+ $HOME/.claude/commands/sim-test.md
26
+ ```
27
+
28
+ Run it with **scenario = `screenshot <locale>`**, substituting the locale resolved
29
+ above. That is the tag sim-test.md matches; passing a bare `screenshot` leaves the
30
+ language unset.
31
+
32
+ ## Equivalent
33
+
34
+ `/multi-agent:test "screenshot tr"` - identical behaviour. Both forms are
35
+ supported; neither is deprecated.
36
+
37
+ ## Requirements
38
+
39
+ - **iOS**: Xcode + a booted Simulator (`xcrun simctl list | grep Booted`)
40
+ - **Android**: Android SDK + a running emulator or USB device (`adb devices`)
41
+ - **MCP**: the `dev-toolkit` MCP server must be installed (tool names start with `mcp__dev-toolkit__`)