Summary
Every ambiguous-match error in asc should list the matching candidates (ID plus a human label) and name the exact flag that accepts one of those IDs, so a caller can recover in one retry without a second discovery call.
Motivation
EAS CLI made every "unable to select X" failure print the available values and the flag to pass, explicitly so that agents driving the CLI can recover without guessing:
asc has roughly 63 sites (git grep -n -i 'ambiguous\|multiple .* found\|more than one' internal/cli | grep -v _test) that fail on ambiguity. Most of them name neither the candidates nor the flag, and the ones that do are inconsistent. For example:
multiple app store versions found for version "1.2.3" and platform "IOS" (use --version-id)names the flag but not the candidate version IDs, so an agent has to run a second list command and correlate the result before retrying. Others (multiple apps found for bundle ID %q; use --app with App Store Connect app ID, multiple beta groups named %q; use group ID, multiple sandbox testers found for %q) give no IDs at all.
Current behavior
- App-by-name / bundle-ID resolution: lists IDs only on one path, no names, no bundle IDs.
- App Store version by version string: says "use --version-id" or "pass --platform" without listing the candidate IDs or platforms.
- TestFlight beta group by name: "use group ID" with no IDs (
testflight), or a bespoke multi-line list (shared). - IAP / subscription stable selectors: bespoke list with
productId=/name=and a generic "Use the explicit ASC ID to disambiguate". - Build-number resolution, app infos, localizations, beta testers, sandbox testers, App Clips, analytics segments, signing certificates, PKCS#12 identities: no candidates.
Proposed contract
A shared formatter in internal/cli/shared (AmbiguousSelectionError with an AmbiguousError(kind, flag, selector, candidates) constructor and AmbiguousCandidate{ID, Label, Extra}) rendering:
Error: 3 apps match "Name"; pass --app with one of:
6759231657 Name com.example.name
1234567890 Name com.example.name-lite
1122334455 Name com.example.name-mac- One candidate per line: ID, then label, then extra context (platform, state, bundle ID, ...).
- Bounded to 10 lines with
... and N more. - When no single flag disambiguates (duplicate localizations, duplicate versions on one platform), the flag clause is omitted and a hint line explains what to do.
- Each site keeps the error class it already returns (usage error / exit 2 stays exit 2; plain errors stay exit 1). Happy-path output is unchanged.
Acceptance criteria
- Shared formatter with unit tests (header, pluralization, bounding, sanitization, usage-class variant).
- Applied to every site in the grep above, prioritizing app-by-name, version-by-string across platforms, TestFlight group by name, subscription/IAP by name or product ID, bundle ID, build-number across platforms, certificate/profile selection.
- cmdtest + httptest coverage for at least five converted sites asserting the stderr text (candidates and flag).
- Exit codes unchanged; no happy-path output changes.
Activity
0No activity yet.