@ai-development-environment/control-agent 0.0.34 → 0.0.35

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 (2) hide show
  1. package/dist/control-agent.js +783 -121
  2. package/package.json +1 -1
@@ -842,6 +842,18 @@ var AgentGraphQLClient = class {
842
842
  );
843
843
  return data.claimAgentJob;
844
844
  }
845
+ async claimSigningSecretTransfer(transferId) {
846
+ const data = await this.request(
847
+ `mutation ClaimSigningSecretTransfer($transferId: ID!) {
848
+ claimSigningSecretTransfer(transferId: $transferId) {
849
+ p12Base64
850
+ passphrase
851
+ }
852
+ }`,
853
+ { transferId }
854
+ );
855
+ return data.claimSigningSecretTransfer;
856
+ }
845
857
  appendLog(jobId, log) {
846
858
  return this.request(
847
859
  `mutation AppendLog($jobId: ID!, $logs: [AgentJobLogInput!]!) {
@@ -2651,7 +2663,11 @@ function parseBuildSourceParsePayload(value) {
2651
2663
  return {
2652
2664
  ...worktreeIdentity(input),
2653
2665
  source: parseBuildSource(input.source),
2654
- scheme: nullableString4(input.scheme, "source parse payload.scheme")
2666
+ scheme: nullableString4(input.scheme, "source parse payload.scheme"),
2667
+ configuration: nullableString4(
2668
+ input.configuration,
2669
+ "source parse payload.configuration"
2670
+ )
2655
2671
  };
2656
2672
  }
2657
2673
  function parseBuildDestinationsPayload(value) {
@@ -2870,6 +2886,23 @@ function parseBuildExportSettings(value) {
2870
2886
  testFlightInternalTestingOnly: booleanValue2(
2871
2887
  input.testFlightInternalTestingOnly,
2872
2888
  "export settings.testFlightInternalTestingOnly"
2889
+ ),
2890
+ stripSwiftSymbols: input.stripSwiftSymbols === void 0 ? true : booleanValue2(
2891
+ input.stripSwiftSymbols,
2892
+ "export settings.stripSwiftSymbols"
2893
+ ),
2894
+ thinning: nullableString4(
2895
+ input.thinning ?? null,
2896
+ "export settings.thinning"
2897
+ ),
2898
+ iCloudContainerEnvironment: input.iCloudContainerEnvironment === null || input.iCloudContainerEnvironment === void 0 ? null : enumValue3(
2899
+ input.iCloudContainerEnvironment,
2900
+ ["Development", "Production"],
2901
+ "export settings.iCloudContainerEnvironment"
2902
+ ),
2903
+ distributionBundleIdentifier: nullableString4(
2904
+ input.distributionBundleIdentifier ?? null,
2905
+ "export settings.distributionBundleIdentifier"
2873
2906
  )
2874
2907
  };
2875
2908
  }
@@ -2914,6 +2947,81 @@ function parseBuildSigningInspectPayload(value) {
2914
2947
  };
2915
2948
  }
2916
2949
 
2950
+ // ../agent-contract/src/signing-assets.ts
2951
+ var SIGNING_ASSETS_SCAN_JOB_KIND = "ios.signing.assets.scan";
2952
+ var SIGNING_PROFILE_READ_JOB_KIND = "ios.signing.profile.read";
2953
+ var SIGNING_PROFILE_INSTALL_JOB_KIND = "ios.signing.profile.install";
2954
+ var SIGNING_PROFILE_DELETE_JOB_KIND = "ios.signing.profile.delete";
2955
+ var SIGNING_IDENTITY_IMPORT_JOB_KIND = "ios.signing.identity.import";
2956
+ var SIGNING_IDENTITY_DELETE_JOB_KIND = "ios.signing.identity.delete";
2957
+ var SIGNING_ASSET_JOB_KINDS = [
2958
+ SIGNING_ASSETS_SCAN_JOB_KIND,
2959
+ SIGNING_PROFILE_READ_JOB_KIND,
2960
+ SIGNING_PROFILE_INSTALL_JOB_KIND,
2961
+ SIGNING_PROFILE_DELETE_JOB_KIND,
2962
+ SIGNING_IDENTITY_IMPORT_JOB_KIND,
2963
+ SIGNING_IDENTITY_DELETE_JOB_KIND
2964
+ ];
2965
+ function objectValue7(value, name) {
2966
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2967
+ throw new Error(`${name} must be an object`);
2968
+ }
2969
+ return value;
2970
+ }
2971
+ function stringValue7(value, name) {
2972
+ if (typeof value !== "string" || !value.trim() || value.includes("\0")) {
2973
+ throw new Error(`${name} must be a non-empty string`);
2974
+ }
2975
+ return value;
2976
+ }
2977
+ function exactKeys2(value, allowed, name) {
2978
+ const unexpected = Object.keys(value).find((key) => !allowed.includes(key));
2979
+ if (unexpected) throw new Error(`Unexpected ${name} field: ${unexpected}`);
2980
+ }
2981
+ function signingScanPayload(value) {
2982
+ const input = objectValue7(value, "signing scan payload");
2983
+ exactKeys2(input, [], "signing scan payload");
2984
+ return {};
2985
+ }
2986
+ function signingProfileKeyPayload(value) {
2987
+ const input = objectValue7(value, "signing profile payload");
2988
+ exactKeys2(input, ["uuid"], "signing profile payload");
2989
+ return { uuid: stringValue7(input.uuid, "signing profile payload.uuid") };
2990
+ }
2991
+ function signingProfileInstallPayload(value) {
2992
+ const input = objectValue7(value, "signing profile install payload");
2993
+ exactKeys2(input, ["contentBase64"], "signing profile install payload");
2994
+ const contentBase64 = stringValue7(
2995
+ input.contentBase64,
2996
+ "signing profile install payload.contentBase64"
2997
+ );
2998
+ if (contentBase64.length > 2 * 1024 * 1024) {
2999
+ throw new Error("Provisioning profile payload is too large");
3000
+ }
3001
+ return { contentBase64 };
3002
+ }
3003
+ function signingIdentityImportPayload(value) {
3004
+ const input = objectValue7(value, "signing identity import payload");
3005
+ exactKeys2(input, ["transferId", "sha256"], "signing identity import payload");
3006
+ const sha256 = stringValue7(input.sha256, "signing identity import sha256");
3007
+ if (!/^[A-Fa-f0-9]{64}$/.test(sha256)) {
3008
+ throw new Error("Signing identity import SHA-256 is invalid");
3009
+ }
3010
+ return {
3011
+ transferId: stringValue7(input.transferId, "signing identity transfer ID"),
3012
+ sha256: sha256.toUpperCase()
3013
+ };
3014
+ }
3015
+ function signingIdentityDeletePayload(value) {
3016
+ const input = objectValue7(value, "signing identity delete payload");
3017
+ exactKeys2(input, ["sha1"], "signing identity delete payload");
3018
+ const sha1 = stringValue7(input.sha1, "signing identity SHA-1");
3019
+ if (!/^[A-Fa-f0-9]{40}$/.test(sha1)) {
3020
+ throw new Error("Signing identity SHA-1 is invalid");
3021
+ }
3022
+ return { sha1: sha1.toUpperCase() };
3023
+ }
3024
+
2917
3025
  // src/inventory.ts
2918
3026
  var AGENT_VERSION = "0.1.0";
2919
3027
  var AGENT_CAPABILITIES = [
@@ -2924,7 +3032,8 @@ var AGENT_CAPABILITIES = [
2924
3032
  CODEBASE_RECONCILE_EVENT_CAPABILITY,
2925
3033
  ...WORKTREE_JOB_KINDS,
2926
3034
  ...SKILL_JOB_KINDS,
2927
- ...IOS_BUILD_JOB_KINDS
3035
+ ...IOS_BUILD_JOB_KINDS,
3036
+ ...SIGNING_ASSET_JOB_KINDS
2928
3037
  ];
2929
3038
  function collectInventory() {
2930
3039
  const disk = statfsSync("/", { bigint: true });
@@ -3054,9 +3163,17 @@ function runCloudflared(payload, timeoutMs, signal, onLog) {
3054
3163
  }
3055
3164
 
3056
3165
  // src/handlers/signing.ts
3057
- import { createHash as createHash2 } from "node:crypto";
3058
- import { readdir, stat as stat2 } from "node:fs/promises";
3059
- import { homedir as homedir2 } from "node:os";
3166
+ import { createHash as createHash2, randomUUID, X509Certificate } from "node:crypto";
3167
+ import {
3168
+ mkdir as mkdir2,
3169
+ mkdtemp,
3170
+ readFile as readFile2,
3171
+ readdir,
3172
+ rm,
3173
+ stat as stat2,
3174
+ writeFile as writeFile2
3175
+ } from "node:fs/promises";
3176
+ import { homedir as homedir2, tmpdir } from "node:os";
3060
3177
  import { basename, join as join2, relative, sep } from "node:path";
3061
3178
 
3062
3179
  // ../agent-contract/src/plist.ts
@@ -3294,7 +3411,7 @@ function text(value) {
3294
3411
  function stringList(value) {
3295
3412
  return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
3296
3413
  }
3297
- async function decodeProfile(path, timeoutMs, signal) {
3414
+ async function decodeProfile(path, timeoutMs, signal, strict = false) {
3298
3415
  try {
3299
3416
  const result = await captureCommand({
3300
3417
  command: "/usr/bin/security",
@@ -3302,16 +3419,29 @@ async function decodeProfile(path, timeoutMs, signal) {
3302
3419
  timeoutMs: Math.min(timeoutMs, 1e4),
3303
3420
  signal
3304
3421
  });
3422
+ if (strict) assertCommandSucceeded(result, `Reading profile ${path}`);
3305
3423
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
3306
3424
  const parsed = parsePlist(result.stdout);
3307
3425
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3426
+ if (strict) throw new Error(`Profile ${path} did not contain a plist`);
3308
3427
  return null;
3309
3428
  }
3310
3429
  return parsed;
3311
- } catch {
3430
+ } catch (error) {
3431
+ if (strict) throw error;
3312
3432
  return null;
3313
3433
  }
3314
3434
  }
3435
+ function assertCommandSucceeded(result, action) {
3436
+ if (result.cancelled) throw new Error(`${action} was cancelled`);
3437
+ if (result.timedOut) throw new Error(`${action} timed out`);
3438
+ if (result.exitCode !== 0) {
3439
+ const detail = result.stderr.trim();
3440
+ throw new Error(
3441
+ `${action} failed${detail ? `: ${detail}` : ` with exit code ${String(result.exitCode)}`}`
3442
+ );
3443
+ }
3444
+ }
3315
3445
  function toProfile(uuid, raw, now) {
3316
3446
  const name = text(raw.Name);
3317
3447
  if (!name) return null;
@@ -3381,6 +3511,66 @@ async function readProfiles(timeoutMs, signal) {
3381
3511
  (left, right) => left.name.localeCompare(right.name)
3382
3512
  );
3383
3513
  }
3514
+ async function decodedProfiles(timeoutMs, signal, strict = false) {
3515
+ const profiles = [];
3516
+ if (strict) signal.throwIfAborted();
3517
+ for (const directory of PROFILE_DIRECTORIES) {
3518
+ let entries;
3519
+ try {
3520
+ entries = await readdir(directory);
3521
+ } catch (error) {
3522
+ if (strict && error.code !== "ENOENT") {
3523
+ throw error;
3524
+ }
3525
+ continue;
3526
+ }
3527
+ for (const entry of entries) {
3528
+ if (!PROFILE_EXTENSIONS.some((suffix) => entry.endsWith(suffix))) {
3529
+ continue;
3530
+ }
3531
+ signal.throwIfAborted();
3532
+ const path = join2(directory, entry);
3533
+ const raw = await decodeProfile(path, timeoutMs, signal, strict);
3534
+ if (!raw) continue;
3535
+ let content;
3536
+ try {
3537
+ content = await readFile2(path);
3538
+ } catch (error) {
3539
+ if (strict) throw error;
3540
+ continue;
3541
+ }
3542
+ profiles.push({
3543
+ path,
3544
+ content,
3545
+ raw,
3546
+ uuid: text(raw.UUID) ?? basename(entry).replace(/\.[^.]+$/, "")
3547
+ });
3548
+ }
3549
+ }
3550
+ return profiles;
3551
+ }
3552
+ function profileAsset(decoded, now) {
3553
+ const profile = toProfile(decoded.uuid, decoded.raw, now);
3554
+ if (!profile) return null;
3555
+ const createdAt = text(decoded.raw.CreationDate);
3556
+ return {
3557
+ uuid: profile.uuid,
3558
+ contentHash: createHash2("sha256").update(decoded.content).digest("hex").toUpperCase(),
3559
+ name: profile.name,
3560
+ profileType: profile.type,
3561
+ bundleId: profile.bundleId,
3562
+ teamId: profile.teamId,
3563
+ teamName: profile.teamName,
3564
+ platforms: profile.platforms,
3565
+ deviceCount: stringList(decoded.raw.ProvisionedDevices).length,
3566
+ deviceUdids: stringList(decoded.raw.ProvisionedDevices),
3567
+ certificateSha1s: profile.certificateSha1s,
3568
+ createdAt,
3569
+ expiresAt: profile.expiresAt,
3570
+ expired: profile.expired,
3571
+ xcodeManaged: profile.xcodeManaged
3572
+ };
3573
+ }
3384
3574
  function dedupeProfiles(profiles) {
3385
3575
  const best = /* @__PURE__ */ new Map();
3386
3576
  for (const profile of profiles) {
@@ -3401,7 +3591,7 @@ function dedupeProfiles(profiles) {
3401
3591
  return [...best.values()];
3402
3592
  }
3403
3593
  var IDENTITY_PATTERN = /^\s*\d+\)\s+([0-9A-F]{40})\s+"(.+)"\s*$/i;
3404
- async function readIdentities(timeoutMs, signal) {
3594
+ async function readIdentities(timeoutMs, signal, strict = false) {
3405
3595
  try {
3406
3596
  const result = await captureCommand({
3407
3597
  command: "/usr/bin/security",
@@ -3409,6 +3599,7 @@ async function readIdentities(timeoutMs, signal) {
3409
3599
  timeoutMs: Math.min(timeoutMs, 1e4),
3410
3600
  signal
3411
3601
  });
3602
+ if (strict) assertCommandSucceeded(result, "Reading signing identities");
3412
3603
  if (result.exitCode !== 0) return [];
3413
3604
  const identities = /* @__PURE__ */ new Map();
3414
3605
  for (const line of result.stdout.split("\n")) {
@@ -3419,10 +3610,80 @@ async function readIdentities(timeoutMs, signal) {
3419
3610
  identities.set(sha1, { sha1, name, teamId: team?.[1] ?? null });
3420
3611
  }
3421
3612
  return [...identities.values()];
3422
- } catch {
3613
+ } catch (error) {
3614
+ if (strict) throw error;
3423
3615
  return [];
3424
3616
  }
3425
3617
  }
3618
+ function commonName(certificate) {
3619
+ return certificate.subject.split(/\n|,\s*/).find((part) => part.startsWith("CN="))?.slice(3) ?? certificate.subject;
3620
+ }
3621
+ function certificateType(name) {
3622
+ const known = [
3623
+ "Apple Development",
3624
+ "Apple Distribution",
3625
+ "iPhone Developer",
3626
+ "iPhone Distribution",
3627
+ "iOS Developer",
3628
+ "iOS Distribution",
3629
+ "Mac Developer",
3630
+ "Mac App Distribution",
3631
+ "Developer ID Application",
3632
+ "Developer ID Installer"
3633
+ ];
3634
+ return known.find((prefix) => name.startsWith(prefix)) ?? null;
3635
+ }
3636
+ function pemCertificates(value) {
3637
+ return value.match(
3638
+ /-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g
3639
+ ) ?? [];
3640
+ }
3641
+ async function readCertificates(timeoutMs, signal, strict = false) {
3642
+ const [certificateResult, identities] = await Promise.all([
3643
+ captureCommand({
3644
+ command: "/usr/bin/security",
3645
+ args: ["find-certificate", "-a", "-p"],
3646
+ timeoutMs: Math.min(timeoutMs, 2e4),
3647
+ signal
3648
+ }),
3649
+ readIdentities(timeoutMs, signal, strict)
3650
+ ]);
3651
+ if (strict) {
3652
+ assertCommandSucceeded(certificateResult, "Reading signing certificates");
3653
+ }
3654
+ if (certificateResult.exitCode !== 0) return [];
3655
+ const identityHashes = new Set(
3656
+ identities.map((identity) => identity.sha1.toUpperCase())
3657
+ );
3658
+ const assets = /* @__PURE__ */ new Map();
3659
+ for (const pem of pemCertificates(certificateResult.stdout)) {
3660
+ try {
3661
+ const certificate = new X509Certificate(pem);
3662
+ const name = commonName(certificate);
3663
+ const type = certificateType(name);
3664
+ if (!type) continue;
3665
+ const sha1 = certificate.fingerprint.replaceAll(":", "").toUpperCase();
3666
+ const expiresAt = new Date(certificate.validTo);
3667
+ const team = /\(([A-Z0-9]{10})\)\s*$/.exec(name);
3668
+ assets.set(sha1, {
3669
+ sha1,
3670
+ sha256: certificate.fingerprint256.replaceAll(":", "").toUpperCase(),
3671
+ name,
3672
+ teamId: team?.[1] ?? null,
3673
+ certificateType: type,
3674
+ notBefore: new Date(certificate.validFrom).toISOString(),
3675
+ expiresAt: expiresAt.toISOString(),
3676
+ expired: expiresAt.getTime() < Date.now(),
3677
+ hasPrivateKey: identityHashes.has(sha1)
3678
+ });
3679
+ } catch {
3680
+ continue;
3681
+ }
3682
+ }
3683
+ return [...assets.values()].sort(
3684
+ (left, right) => left.name.localeCompare(right.name)
3685
+ );
3686
+ }
3426
3687
  async function readArchiveBundles(archivePath, timeoutMs, signal) {
3427
3688
  const products = join2(archivePath, "Products");
3428
3689
  const bundles = [];
@@ -3543,6 +3804,139 @@ var inspectIosSigning = async (payload, timeoutMs, signal) => {
3543
3804
  ...inspection
3544
3805
  };
3545
3806
  };
3807
+ var successfulProcess = {
3808
+ exitCode: 0,
3809
+ signal: null,
3810
+ timedOut: false,
3811
+ cancelled: false
3812
+ };
3813
+ var scanSigningAssets = async (payload, timeoutMs, signal) => {
3814
+ signingScanPayload(payload);
3815
+ const [decoded, certificates] = await Promise.all([
3816
+ decodedProfiles(timeoutMs, signal, true),
3817
+ readCertificates(timeoutMs, signal, true)
3818
+ ]);
3819
+ const byUuid = /* @__PURE__ */ new Map();
3820
+ for (const profile of decoded) {
3821
+ const asset = profileAsset(profile, Date.now());
3822
+ if (!asset) continue;
3823
+ const existing = byUuid.get(asset.uuid);
3824
+ if (!existing || (asset.expiresAt ?? "") > (existing.expiresAt ?? "")) {
3825
+ byUuid.set(asset.uuid, asset);
3826
+ }
3827
+ }
3828
+ return {
3829
+ ...successfulProcess,
3830
+ profiles: [...byUuid.values()].sort(
3831
+ (left, right) => left.name.localeCompare(right.name)
3832
+ ),
3833
+ certificates,
3834
+ warnings: []
3835
+ };
3836
+ };
3837
+ async function findDecodedProfile(uuid, timeoutMs, signal) {
3838
+ const profile = (await decodedProfiles(timeoutMs, signal)).find(
3839
+ (entry) => entry.uuid === uuid
3840
+ );
3841
+ if (!profile) throw new Error("Provisioning profile is no longer installed");
3842
+ return profile;
3843
+ }
3844
+ var readSigningProfile = async (payload, timeoutMs, signal) => {
3845
+ const { uuid } = signingProfileKeyPayload(payload);
3846
+ const profile = await findDecodedProfile(uuid, timeoutMs, signal);
3847
+ return {
3848
+ ...successfulProcess,
3849
+ uuid,
3850
+ contentBase64: profile.content.toString("base64"),
3851
+ sha256: createHash2("sha256").update(profile.content).digest("hex").toUpperCase()
3852
+ };
3853
+ };
3854
+ var installSigningProfile = async (payload, timeoutMs, signal) => {
3855
+ const { contentBase64 } = signingProfileInstallPayload(payload);
3856
+ const content = Buffer.from(contentBase64, "base64");
3857
+ if (!content.length) throw new Error("Provisioning profile is empty");
3858
+ const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-profile-"));
3859
+ const temporaryPath = join2(temporaryRoot, `${randomUUID()}.mobileprovision`);
3860
+ try {
3861
+ await writeFile2(temporaryPath, content, { mode: 384 });
3862
+ const raw = await decodeProfile(temporaryPath, timeoutMs, signal);
3863
+ if (!raw) throw new Error("Provisioning profile is invalid or unsigned");
3864
+ const uuid = text(raw.UUID);
3865
+ if (!uuid) throw new Error("Provisioning profile UUID is missing");
3866
+ const directory = PROFILE_DIRECTORIES[0];
3867
+ await mkdir2(directory, { recursive: true, mode: 448 });
3868
+ const destination = join2(directory, `${uuid}.mobileprovision`);
3869
+ await writeFile2(destination, content, { mode: 384 });
3870
+ return { ...successfulProcess, uuid };
3871
+ } finally {
3872
+ await rm(temporaryRoot, { recursive: true, force: true });
3873
+ }
3874
+ };
3875
+ var deleteSigningProfile = async (payload, timeoutMs, signal) => {
3876
+ const { uuid } = signingProfileKeyPayload(payload);
3877
+ const matches = (await decodedProfiles(timeoutMs, signal)).filter(
3878
+ (entry) => entry.uuid === uuid
3879
+ );
3880
+ for (const profile of matches) {
3881
+ signal.throwIfAborted();
3882
+ await rm(profile.path, { force: false });
3883
+ }
3884
+ return { ...successfulProcess, uuid, deleted: matches.length };
3885
+ };
3886
+ var importSigningIdentity = async (payload, timeoutMs, signal, _onLog, context) => {
3887
+ const input = signingIdentityImportPayload(payload);
3888
+ if (!context?.claimSigningSecretTransfer) {
3889
+ throw new Error("This agent cannot claim signing secret transfers");
3890
+ }
3891
+ const secret = await context.claimSigningSecretTransfer(input.transferId);
3892
+ const p12 = Buffer.from(secret.p12Base64, "base64");
3893
+ const hash = createHash2("sha256").update(p12).digest("hex").toUpperCase();
3894
+ if (hash !== input.sha256)
3895
+ throw new Error("Signing identity transfer changed");
3896
+ const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-identity-"));
3897
+ const path = join2(temporaryRoot, "identity.p12");
3898
+ try {
3899
+ await writeFile2(path, p12, { mode: 384 });
3900
+ const result = await captureCommand({
3901
+ command: "/usr/bin/security",
3902
+ args: [
3903
+ "import",
3904
+ path,
3905
+ "-P",
3906
+ secret.passphrase,
3907
+ "-T",
3908
+ "/usr/bin/codesign",
3909
+ "-T",
3910
+ "/usr/bin/security"
3911
+ ],
3912
+ timeoutMs: Math.min(timeoutMs, 6e4),
3913
+ signal
3914
+ });
3915
+ if (result.exitCode !== 0) {
3916
+ throw new Error(
3917
+ result.stderr.trim() || "Could not import signing identity"
3918
+ );
3919
+ }
3920
+ return { ...successfulProcess, sha256: input.sha256 };
3921
+ } finally {
3922
+ await rm(temporaryRoot, { recursive: true, force: true });
3923
+ }
3924
+ };
3925
+ var deleteSigningIdentity = async (payload, timeoutMs, signal) => {
3926
+ const { sha1 } = signingIdentityDeletePayload(payload);
3927
+ const result = await captureCommand({
3928
+ command: "/usr/bin/security",
3929
+ args: ["delete-identity", "-Z", sha1],
3930
+ timeoutMs: Math.min(timeoutMs, 3e4),
3931
+ signal
3932
+ });
3933
+ if (result.exitCode !== 0) {
3934
+ throw new Error(
3935
+ result.stderr.trim() || "Could not delete signing identity"
3936
+ );
3937
+ }
3938
+ return { ...successfulProcess, sha1 };
3939
+ };
3546
3940
 
3547
3941
  // src/handlers/ccusage.ts
3548
3942
  import { Buffer as Buffer2 } from "node:buffer";
@@ -3599,10 +3993,10 @@ async function runCcusage(payload, timeoutMs, signal, onLog) {
3599
3993
  }
3600
3994
 
3601
3995
  // src/handlers/build-data.ts
3602
- import { lstat, opendir, readdir as readdir2, realpath, rm } from "node:fs/promises";
3996
+ import { lstat, opendir, readdir as readdir2, realpath, rm as rm2 } from "node:fs/promises";
3603
3997
  import { homedir as homedir3 } from "node:os";
3604
3998
  import { basename as basename2, dirname as dirname2, isAbsolute, join as join3, resolve } from "node:path";
3605
- var successfulProcess = {
3999
+ var successfulProcess2 = {
3606
4000
  exitCode: 0,
3607
4001
  signal: null,
3608
4002
  timedOut: false,
@@ -3695,6 +4089,43 @@ async function scanRoot(configuredRoot, timeoutMs, signal) {
3695
4089
  entries.sort((first, second) => first.name.localeCompare(second.name));
3696
4090
  return { entries, warning: null };
3697
4091
  }
4092
+ async function scanDeviceSupport(signal) {
4093
+ const configuredRoot = join3(
4094
+ process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ?? homedir3(),
4095
+ ...process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ? [] : ["Library", "Developer", "Xcode", "iOS DeviceSupport"]
4096
+ );
4097
+ signal.throwIfAborted();
4098
+ let rootPath2;
4099
+ try {
4100
+ rootPath2 = await realpath(configuredRoot);
4101
+ } catch (error) {
4102
+ if (error.code === "ENOENT") {
4103
+ return { entries: [], warning: null };
4104
+ }
4105
+ return {
4106
+ entries: [],
4107
+ warning: `${configuredRoot}: ${errorMessage(error)}`
4108
+ };
4109
+ }
4110
+ try {
4111
+ const children = await readdir2(rootPath2, { withFileTypes: true });
4112
+ return {
4113
+ entries: children.filter((child) => child.isDirectory() && !child.isSymbolicLink()).map((child) => ({
4114
+ path: join3(rootPath2, child.name),
4115
+ rootPath: rootPath2,
4116
+ name: child.name,
4117
+ kind: "DEVICE_SUPPORT",
4118
+ workspacePath: null
4119
+ })).sort((first, second) => first.name.localeCompare(second.name)),
4120
+ warning: null
4121
+ };
4122
+ } catch (error) {
4123
+ return {
4124
+ entries: [],
4125
+ warning: `${rootPath2}: ${errorMessage(error)}`
4126
+ };
4127
+ }
4128
+ }
3698
4129
  var scanBuildData = async (rawPayload, timeoutMs, signal) => {
3699
4130
  const payload = buildDataScanPayload(rawPayload);
3700
4131
  const roots = await configuredRoots(payload);
@@ -3714,7 +4145,10 @@ var scanBuildData = async (rawPayload, timeoutMs, signal) => {
3714
4145
  entries.push(...result.entries);
3715
4146
  if (result.warning) warnings.push(result.warning);
3716
4147
  }
3717
- return { ...successfulProcess, entries, warnings };
4148
+ const deviceSupport = await scanDeviceSupport(signal);
4149
+ entries.push(...deviceSupport.entries);
4150
+ if (deviceSupport.warning) warnings.push(deviceSupport.warning);
4151
+ return { ...successfulProcess2, entries, warnings };
3718
4152
  };
3719
4153
  function assertDirectChild(rootPath2, path) {
3720
4154
  if (!isAbsolute(rootPath2) || !isAbsolute(path)) {
@@ -3772,7 +4206,7 @@ var sizeBuildData = async (rawPayload, _timeoutMs, signal) => {
3772
4206
  });
3773
4207
  }
3774
4208
  }
3775
- return { ...successfulProcess, sizes };
4209
+ return { ...successfulProcess2, sizes };
3776
4210
  };
3777
4211
  var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3778
4212
  const payload = buildDataTargetsPayload(rawPayload);
@@ -3789,7 +4223,7 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3789
4223
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
3790
4224
  throw new Error("Build Data target is not a directory");
3791
4225
  }
3792
- await rm(target2.path, { recursive: true, force: false, maxRetries: 3 });
4226
+ await rm2(target2.path, { recursive: true, force: false, maxRetries: 3 });
3793
4227
  deleted.push({ path: target2.path, deleted: true, error: null });
3794
4228
  } catch (error) {
3795
4229
  signal.throwIfAborted();
@@ -3800,14 +4234,14 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3800
4234
  });
3801
4235
  }
3802
4236
  }
3803
- return { ...successfulProcess, deleted };
4237
+ return { ...successfulProcess2, deleted };
3804
4238
  };
3805
4239
 
3806
4240
  // src/handlers/codebases.ts
3807
4241
  import { readdir as readdir3, realpath as realpath2, stat as stat3 } from "node:fs/promises";
3808
4242
  import { homedir as homedir4 } from "node:os";
3809
4243
  import { dirname as dirname3, join as join4, resolve as resolve2 } from "node:path";
3810
- var successfulProcess2 = {
4244
+ var successfulProcess3 = {
3811
4245
  exitCode: 0,
3812
4246
  signal: null,
3813
4247
  timedOut: false,
@@ -3898,7 +4332,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3898
4332
  throw new Error("Folder is not a directory");
3899
4333
  } catch (error) {
3900
4334
  return {
3901
- ...successfulProcess2,
4335
+ ...successfulProcess3,
3902
4336
  snapshot: {
3903
4337
  ...base,
3904
4338
  availability: "MISSING",
@@ -3915,7 +4349,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3915
4349
  );
3916
4350
  if (rootResult.exitCode !== 0) {
3917
4351
  return {
3918
- ...successfulProcess2,
4352
+ ...successfulProcess3,
3919
4353
  snapshot: {
3920
4354
  ...base,
3921
4355
  folder: selected,
@@ -3935,7 +4369,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3935
4369
  );
3936
4370
  if (bare.stdout.trim() === "true") {
3937
4371
  return {
3938
- ...successfulProcess2,
4372
+ ...successfulProcess3,
3939
4373
  snapshot: {
3940
4374
  ...base,
3941
4375
  folder,
@@ -3967,7 +4401,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3967
4401
  ]);
3968
4402
  if (originResult.exitCode !== 0) {
3969
4403
  return {
3970
- ...successfulProcess2,
4404
+ ...successfulProcess3,
3971
4405
  snapshot: {
3972
4406
  ...base,
3973
4407
  folder,
@@ -4014,7 +4448,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
4014
4448
  const syncState = !branch ? "DETACHED" : !upstream ? "NO_UPSTREAM" : ahead === null || behind === null ? "UNKNOWN" : ahead > 0 && behind > 0 ? "DIVERGED" : ahead > 0 ? "AHEAD" : behind > 0 ? "BEHIND" : "IN_SYNC";
4015
4449
  const mismatch = expectedOrigin !== void 0 && origin2.canonicalOrigin !== expectedOrigin;
4016
4450
  return {
4017
- ...successfulProcess2,
4451
+ ...successfulProcess3,
4018
4452
  snapshot: {
4019
4453
  folder,
4020
4454
  observedOrigin: origin2.sanitizedOrigin,
@@ -4036,7 +4470,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
4036
4470
  } catch (error) {
4037
4471
  if (error instanceof InterruptedGitInspection) return error.result;
4038
4472
  return {
4039
- ...successfulProcess2,
4473
+ ...successfulProcess3,
4040
4474
  snapshot: {
4041
4475
  ...base,
4042
4476
  folder: selected,
@@ -4097,7 +4531,7 @@ var browseCodebaseDirectories = async (payload) => {
4097
4531
  entries: entries.slice(0, 1e3),
4098
4532
  truncated: entries.length > 1e3
4099
4533
  };
4100
- return { ...successfulProcess2, listing };
4534
+ return { ...successfulProcess3, listing };
4101
4535
  };
4102
4536
  var inspectCodebaseFolder = async (payload, timeoutMs, signal) => {
4103
4537
  const input = codebaseJobPayload(payload);
@@ -4183,7 +4617,7 @@ var fetchCodebase = async (payload, timeoutMs, signal) => {
4183
4617
  if (!("snapshot" in beforeResult)) return beforeResult;
4184
4618
  const before = beforeResult.snapshot;
4185
4619
  if (before.availability !== "AVAILABLE") {
4186
- return { ...successfulProcess2, exitCode: 1, snapshot: before };
4620
+ return { ...successfulProcess3, exitCode: 1, snapshot: before };
4187
4621
  }
4188
4622
  let result;
4189
4623
  try {
@@ -4379,7 +4813,7 @@ var inspectCodebaseGit = async (payload, timeoutMs, signal) => {
4379
4813
  );
4380
4814
  if (input.action === "STATE") {
4381
4815
  return {
4382
- ...successfulProcess2,
4816
+ ...successfulProcess3,
4383
4817
  state: await inspectCodebaseGitState(folder, timeoutMs, signal)
4384
4818
  };
4385
4819
  }
@@ -4404,7 +4838,7 @@ var inspectCodebaseGit = async (payload, timeoutMs, signal) => {
4404
4838
  );
4405
4839
  const patch = truncateUtf8(result.stdout, MAX_CODEBASE_STASH_PATCH_BYTES);
4406
4840
  return {
4407
- ...successfulProcess2,
4841
+ ...successfulProcess3,
4408
4842
  diff: {
4409
4843
  oid: input.stashOid,
4410
4844
  patch: patch.value,
@@ -4623,7 +5057,7 @@ var operateCodebaseGit = async (payload, timeoutMs, signal) => {
4623
5057
  }
4624
5058
  }
4625
5059
  return {
4626
- ...successfulProcess2,
5060
+ ...successfulProcess3,
4627
5061
  snapshot: await inspectCodebase(
4628
5062
  folder,
4629
5063
  Math.min(timeoutMs, 3e4),
@@ -4640,25 +5074,25 @@ var operateCodebaseGit = async (payload, timeoutMs, signal) => {
4640
5074
 
4641
5075
  // src/handlers/skills.ts
4642
5076
  import { execFile } from "node:child_process";
4643
- import { randomUUID } from "node:crypto";
5077
+ import { randomUUID as randomUUID2 } from "node:crypto";
4644
5078
  import {
4645
5079
  access,
4646
5080
  chmod as chmod2,
4647
5081
  lstat as lstat2,
4648
- mkdir as mkdir2,
4649
- readFile as readFile2,
5082
+ mkdir as mkdir3,
5083
+ readFile as readFile3,
4650
5084
  realpath as realpath3,
4651
5085
  readdir as readdir4,
4652
5086
  rename as rename2,
4653
- rm as rm2,
5087
+ rm as rm3,
4654
5088
  stat as stat4,
4655
- writeFile as writeFile2
5089
+ writeFile as writeFile3
4656
5090
  } from "node:fs/promises";
4657
5091
  import { homedir as homedir5 } from "node:os";
4658
5092
  import { dirname as dirname4, isAbsolute as isAbsolute2, join as join5, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
4659
5093
  import { promisify } from "node:util";
4660
5094
  var executeFile = promisify(execFile);
4661
- var successfulProcess3 = {
5095
+ var successfulProcess4 = {
4662
5096
  exitCode: 0,
4663
5097
  signal: null,
4664
5098
  timedOut: false,
@@ -4767,7 +5201,7 @@ async function listPackageFiles(skillDirectory) {
4767
5201
  throw new Error("Skill exceeds the package size limit");
4768
5202
  files.push({
4769
5203
  path: relative2(skillDirectory, path).split(sep2).join("/"),
4770
- contentsBase64: (await readFile2(path)).toString("base64"),
5204
+ contentsBase64: (await readFile3(path)).toString("base64"),
4771
5205
  executable: (metadata.mode & 73) !== 0
4772
5206
  });
4773
5207
  }
@@ -4889,7 +5323,7 @@ var scanSkills = async (payload) => {
4889
5323
  )
4890
5324
  )).flat();
4891
5325
  return {
4892
- ...successfulProcess3,
5326
+ ...successfulProcess4,
4893
5327
  configuredTools: observations,
4894
5328
  installations,
4895
5329
  warnings: warnings.slice(0, 500)
@@ -4914,7 +5348,7 @@ var readSkills = async (payload) => {
4914
5348
  package: await readPackage(join5(root, request.skillName))
4915
5349
  });
4916
5350
  }
4917
- return { ...successfulProcess3, packages };
5351
+ return { ...successfulProcess4, packages };
4918
5352
  };
4919
5353
  async function gitExcludePath(folder) {
4920
5354
  const result = await executeFile("git", [
@@ -4929,10 +5363,10 @@ async function gitExcludePath(folder) {
4929
5363
  }
4930
5364
  async function updateManagedExclude(folder, relativeSkillPath, present) {
4931
5365
  const excludePath = await gitExcludePath(folder);
4932
- await mkdir2(dirname4(excludePath), { recursive: true });
5366
+ await mkdir3(dirname4(excludePath), { recursive: true });
4933
5367
  let existing = "";
4934
5368
  try {
4935
- existing = await readFile2(excludePath, "utf8");
5369
+ existing = await readFile3(excludePath, "utf8");
4936
5370
  } catch {
4937
5371
  }
4938
5372
  const start = existing.indexOf(MANAGED_EXCLUDE_START);
@@ -4952,7 +5386,7 @@ async function updateManagedExclude(folder, relativeSkillPath, present) {
4952
5386
  const block = managed.size ? `${MANAGED_EXCLUDE_START}
4953
5387
  ${[...managed].sort().join("\n")}
4954
5388
  ${MANAGED_EXCLUDE_END}` : "";
4955
- await writeFile2(
5389
+ await writeFile3(
4956
5390
  excludePath,
4957
5391
  `${[before, block, after].filter(Boolean).join("\n\n")}
4958
5392
  `,
@@ -4975,17 +5409,17 @@ async function writePackage(location, skillPackage) {
4975
5409
  const root = rootPath(location);
4976
5410
  const destination = join5(root, skillPackage.name);
4977
5411
  await assertUntracked(location, destination);
4978
- await mkdir2(root, { recursive: true });
4979
- const temporary = join5(root, `.${skillPackage.name}.${randomUUID()}.tmp`);
4980
- const backup = join5(root, `.${skillPackage.name}.${randomUUID()}.bak`);
4981
- await mkdir2(temporary, { recursive: true });
5412
+ await mkdir3(root, { recursive: true });
5413
+ const temporary = join5(root, `.${skillPackage.name}.${randomUUID2()}.tmp`);
5414
+ const backup = join5(root, `.${skillPackage.name}.${randomUUID2()}.bak`);
5415
+ await mkdir3(temporary, { recursive: true });
4982
5416
  try {
4983
5417
  for (const file of skillPackage.files) {
4984
5418
  const path = resolve3(temporary, ...file.path.split("/"));
4985
5419
  if (!path.startsWith(`${temporary}${sep2}`))
4986
5420
  throw new Error("Skill file escaped temporary directory");
4987
- await mkdir2(dirname4(path), { recursive: true });
4988
- await writeFile2(path, Buffer.from(file.contentsBase64, "base64"));
5421
+ await mkdir3(dirname4(path), { recursive: true });
5422
+ await writeFile3(path, Buffer.from(file.contentsBase64, "base64"));
4989
5423
  await chmod2(path, file.executable ? 493 : 420);
4990
5424
  }
4991
5425
  let hadDestination = false;
@@ -4998,14 +5432,14 @@ async function writePackage(location, skillPackage) {
4998
5432
  }
4999
5433
  try {
5000
5434
  await rename2(temporary, destination);
5001
- if (hadDestination) await rm2(backup, { recursive: true, force: true });
5435
+ if (hadDestination) await rm3(backup, { recursive: true, force: true });
5002
5436
  } catch (error) {
5003
5437
  if (hadDestination) await rename2(backup, destination);
5004
5438
  throw error;
5005
5439
  }
5006
5440
  } finally {
5007
- await rm2(temporary, { recursive: true, force: true });
5008
- await rm2(backup, { recursive: true, force: true });
5441
+ await rm3(temporary, { recursive: true, force: true });
5442
+ await rm3(backup, { recursive: true, force: true });
5009
5443
  }
5010
5444
  return destination;
5011
5445
  }
@@ -5025,7 +5459,7 @@ var applySkills = async (payload) => {
5025
5459
  packageHash: operation.package.packageHash
5026
5460
  });
5027
5461
  } else {
5028
- await rm2(destination, { recursive: true, force: true });
5462
+ await rm3(destination, { recursive: true, force: true });
5029
5463
  results.push({
5030
5464
  kind: operation.kind,
5031
5465
  path: destination,
@@ -5040,13 +5474,13 @@ var applySkills = async (payload) => {
5040
5474
  );
5041
5475
  }
5042
5476
  }
5043
- return { ...successfulProcess3, results };
5477
+ return { ...successfulProcess4, results };
5044
5478
  };
5045
5479
 
5046
5480
  // src/handlers/worktrees.ts
5047
5481
  import { createWriteStream, watch } from "node:fs";
5048
- import { mkdtemp, open, readFile as readFile3, realpath as realpath4, rm as rm3, stat as stat5 } from "node:fs/promises";
5049
- import { tmpdir } from "node:os";
5482
+ import { mkdtemp as mkdtemp2, open, readFile as readFile4, realpath as realpath4, rm as rm4, stat as stat5 } from "node:fs/promises";
5483
+ import { tmpdir as tmpdir2 } from "node:os";
5050
5484
  import { basename as basename3, dirname as dirname5, join as join6, relative as relative4 } from "node:path";
5051
5485
  import { spawn as spawn4 } from "node:child_process";
5052
5486
 
@@ -5242,7 +5676,7 @@ async function worktreeCodeStateHash(folder, timeoutMs, signal) {
5242
5676
  }
5243
5677
 
5244
5678
  // src/handlers/worktrees.ts
5245
- var successfulProcess4 = {
5679
+ var successfulProcess5 = {
5246
5680
  exitCode: 0,
5247
5681
  signal: null,
5248
5682
  timedOut: false,
@@ -5686,7 +6120,7 @@ async function untrackedLines(folder, path) {
5686
6120
  try {
5687
6121
  const file = await stat5(`${folder}/${path}`);
5688
6122
  if (!file.isFile() || file.size > 1024 * 1024) return null;
5689
- const contents = await readFile3(`${folder}/${path}`);
6123
+ const contents = await readFile4(`${folder}/${path}`);
5690
6124
  if (contents.includes(0)) return null;
5691
6125
  const text2 = contents.toString("utf8");
5692
6126
  return text2 ? text2.split("\n").length - (text2.endsWith("\n") ? 1 : 0) : 0;
@@ -6137,7 +6571,7 @@ var inspectWorktreeDiff = async (payload, timeoutMs, signal) => {
6137
6571
  const input = worktreeDiffPayload(payload);
6138
6572
  const folder = await validateWorktree(input, timeoutMs, signal);
6139
6573
  return {
6140
- ...successfulProcess4,
6574
+ ...successfulProcess5,
6141
6575
  diff: await inspectRequestedDiff(input, folder, timeoutMs, signal)
6142
6576
  };
6143
6577
  };
@@ -6239,7 +6673,7 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
6239
6673
  if (!/^\d+$/.test(size) || Number(size) > 20 * 1024 * 1024) {
6240
6674
  throw new Error("Diff image exceeds the 20 MiB limit");
6241
6675
  }
6242
- temporaryDirectory = await mkdtemp(join6(tmpdir(), "ade-diff-image-"));
6676
+ temporaryDirectory = await mkdtemp2(join6(tmpdir2(), "ade-diff-image-"));
6243
6677
  uploadPath = join6(temporaryDirectory, basename3(input.path));
6244
6678
  await writeGitObject(
6245
6679
  folder,
@@ -6259,10 +6693,10 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
6259
6693
  filename: basename3(input.path),
6260
6694
  contentType: imageContentType(input.path)
6261
6695
  });
6262
- return successfulProcess4;
6696
+ return successfulProcess5;
6263
6697
  } finally {
6264
6698
  if (temporaryDirectory) {
6265
- await rm3(temporaryDirectory, { recursive: true, force: true });
6699
+ await rm4(temporaryDirectory, { recursive: true, force: true });
6266
6700
  }
6267
6701
  }
6268
6702
  };
@@ -6274,11 +6708,11 @@ var watchWorktree = async (payload, timeoutMs, signal, _onLog, context) => {
6274
6708
  closeWorktreeWatch(current);
6275
6709
  activeWorktreeWatches.delete(input.gitDirectory);
6276
6710
  }
6277
- return successfulProcess4;
6711
+ return successfulProcess5;
6278
6712
  }
6279
6713
  if (!context) throw new Error("Worktree activity reporting is unavailable");
6280
6714
  const folder = await validateWorktree(input, timeoutMs, signal);
6281
- if (current?.watchId === input.watchId) return successfulProcess4;
6715
+ if (current?.watchId === input.watchId) return successfulProcess5;
6282
6716
  if (current) {
6283
6717
  closeWorktreeWatch(current);
6284
6718
  activeWorktreeWatches.delete(input.gitDirectory);
@@ -6320,14 +6754,14 @@ var watchWorktree = async (payload, timeoutMs, signal, _onLog, context) => {
6320
6754
  activeWorktreeWatches.delete(input.gitDirectory);
6321
6755
  throw error;
6322
6756
  }
6323
- return successfulProcess4;
6757
+ return successfulProcess5;
6324
6758
  };
6325
6759
  var inspectWorktree = async (payload, timeoutMs, signal) => {
6326
6760
  const input = worktreeJobPayload(payload);
6327
6761
  const folder = await validateWorktree(input, timeoutMs, signal);
6328
6762
  if (!input.baseBranch) throw new Error("A base branch is required");
6329
6763
  return {
6330
- ...successfulProcess4,
6764
+ ...successfulProcess5,
6331
6765
  detail: await inspectWorktreeDetail(
6332
6766
  folder,
6333
6767
  input.baseBranch,
@@ -6558,7 +6992,7 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
6558
6992
  throw new Error(worktree.error || "Could not inspect the updated worktree");
6559
6993
  }
6560
6994
  return {
6561
- ...successfulProcess4,
6995
+ ...successfulProcess5,
6562
6996
  worktree,
6563
6997
  branch,
6564
6998
  baseBranch: input.baseBranch,
@@ -6613,7 +7047,7 @@ var pushMovedWorktree = async (payload, timeoutMs, signal) => {
6613
7047
  throw new Error("The source branch changed while it was being pushed");
6614
7048
  }
6615
7049
  return {
6616
- ...successfulProcess4,
7050
+ ...successfulProcess5,
6617
7051
  moveId: input.moveId,
6618
7052
  branch,
6619
7053
  headSha: pushedHeadSha
@@ -6813,7 +7247,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
6813
7247
  if (switched.exitCode !== 0) {
6814
7248
  if (!input.stashOnFailure && hasChanges(targetChanges)) {
6815
7249
  return {
6816
- ...successfulProcess4,
7250
+ ...successfulProcess5,
6817
7251
  moveId: input.moveId,
6818
7252
  outcome: "NEEDS_STASH",
6819
7253
  message: cleanError2(
@@ -6858,7 +7292,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
6858
7292
  );
6859
7293
  }
6860
7294
  return {
6861
- ...successfulProcess4,
7295
+ ...successfulProcess5,
6862
7296
  moveId: input.moveId,
6863
7297
  outcome: "CHECKED_OUT",
6864
7298
  worktree,
@@ -6956,7 +7390,7 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
6956
7390
  );
6957
7391
  }
6958
7392
  return {
6959
- ...successfulProcess4,
7393
+ ...successfulProcess5,
6960
7394
  moveId: input.moveId,
6961
7395
  deleted: true,
6962
7396
  branch,
@@ -7050,7 +7484,7 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
7050
7484
  break;
7051
7485
  }
7052
7486
  return {
7053
- ...successfulProcess4,
7487
+ ...successfulProcess5,
7054
7488
  worktree: await inspectWorktreeItem(
7055
7489
  folder,
7056
7490
  folder,
@@ -7063,22 +7497,22 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
7063
7497
  };
7064
7498
 
7065
7499
  // src/handlers/builds.ts
7066
- import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
7500
+ import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
7067
7501
  import {
7068
7502
  cp,
7069
- mkdir as mkdir3,
7070
- mkdtemp as mkdtemp2,
7503
+ mkdir as mkdir4,
7504
+ mkdtemp as mkdtemp3,
7071
7505
  open as open2,
7072
7506
  readdir as readdir5,
7073
- readFile as readFile4,
7507
+ readFile as readFile5,
7074
7508
  realpath as realpath5,
7075
7509
  rename as rename3,
7076
- rm as rm4,
7510
+ rm as rm5,
7077
7511
  stat as stat6,
7078
- writeFile as writeFile3
7512
+ writeFile as writeFile4
7079
7513
  } from "node:fs/promises";
7080
7514
  import { createReadStream as createReadStream3, createWriteStream as createWriteStream2 } from "node:fs";
7081
- import { tmpdir as tmpdir2 } from "node:os";
7515
+ import { tmpdir as tmpdir3 } from "node:os";
7082
7516
  import { pipeline } from "node:stream/promises";
7083
7517
  import {
7084
7518
  basename as basename4,
@@ -7090,7 +7524,7 @@ import {
7090
7524
  sep as sep4
7091
7525
  } from "node:path";
7092
7526
  import { spawn as spawn5 } from "node:child_process";
7093
- var successfulProcess5 = {
7527
+ var successfulProcess6 = {
7094
7528
  exitCode: 0,
7095
7529
  signal: null,
7096
7530
  timedOut: false,
@@ -7283,7 +7717,7 @@ async function workspaceProjectPaths(workspacePath2, folder) {
7283
7717
  const contentsPath = join7(workspacePath2, "contents.xcworkspacedata");
7284
7718
  let contents;
7285
7719
  try {
7286
- contents = await readFile4(contentsPath, "utf8");
7720
+ contents = await readFile5(contentsPath, "utf8");
7287
7721
  } catch {
7288
7722
  return [];
7289
7723
  }
@@ -7384,11 +7818,211 @@ async function testPlans(source, absolutePath, folder, scheme, timeoutMs, signal
7384
7818
  }
7385
7819
  return [];
7386
7820
  }
7821
+ function buildSetting(settings, key) {
7822
+ const value = settings[key];
7823
+ return typeof value === "string" && value.trim() ? value.trim() : null;
7824
+ }
7825
+ function signingPlatform(settings) {
7826
+ const platform = buildSetting(settings, "PLATFORM_NAME");
7827
+ if (platform === "iphoneos") return "iOS";
7828
+ if (platform === "watchos") return "watchOS";
7829
+ if (platform === "appletvos") return "tvOS";
7830
+ if (platform === "xros") return "visionOS";
7831
+ if (platform === "macosx") return "macOS";
7832
+ return platform;
7833
+ }
7834
+ function requiresProvisioningProfile(productType) {
7835
+ return typeof productType === "string" && (productType.includes("application") || productType.includes("app-extension") || productType.includes("watchkit"));
7836
+ }
7837
+ function pbxObject(objects, id) {
7838
+ if (typeof id !== "string") return null;
7839
+ const value = objects[id];
7840
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
7841
+ }
7842
+ function dependentSigningTargetNamesFromPbxProject(value, rootTargetNames) {
7843
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
7844
+ const rawObjects = value.objects;
7845
+ if (!rawObjects || typeof rawObjects !== "object" || Array.isArray(rawObjects))
7846
+ return [];
7847
+ const objects = rawObjects;
7848
+ const roots = new Set(rootTargetNames);
7849
+ const targetEntries = Object.entries(objects).filter(([, target2]) => {
7850
+ if (!target2 || typeof target2 !== "object" || Array.isArray(target2)) {
7851
+ return false;
7852
+ }
7853
+ const record = target2;
7854
+ return (record.isa === "PBXNativeTarget" || record.isa === "PBXAggregateTarget") && typeof record.name === "string";
7855
+ });
7856
+ const queue = targetEntries.filter(
7857
+ ([, target2]) => roots.has(target2.name)
7858
+ ).map(([id]) => id);
7859
+ const visited = new Set(queue);
7860
+ const signingTargets = [];
7861
+ while (queue.length) {
7862
+ const target2 = pbxObject(objects, queue.shift());
7863
+ if (!target2 || !Array.isArray(target2.dependencies)) continue;
7864
+ for (const dependencyId of target2.dependencies) {
7865
+ const dependency = pbxObject(objects, dependencyId);
7866
+ const dependentTargetId = dependency?.target;
7867
+ if (typeof dependentTargetId !== "string") continue;
7868
+ const dependentTarget = pbxObject(objects, dependentTargetId);
7869
+ if (!dependentTarget) continue;
7870
+ if (!visited.has(dependentTargetId)) {
7871
+ visited.add(dependentTargetId);
7872
+ queue.push(dependentTargetId);
7873
+ }
7874
+ const name = dependentTarget.name;
7875
+ if (typeof name === "string" && !roots.has(name) && requiresProvisioningProfile(dependentTarget.productType)) {
7876
+ signingTargets.push(name);
7877
+ }
7878
+ }
7879
+ }
7880
+ return uniqueSorted(signingTargets);
7881
+ }
7882
+ function signingRequirementsFromBuildSettings(value) {
7883
+ if (!Array.isArray(value)) return [];
7884
+ const requirements = /* @__PURE__ */ new Map();
7885
+ for (const entry of value) {
7886
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
7887
+ const record = entry;
7888
+ const rawSettings = record.buildSettings;
7889
+ if (!rawSettings || typeof rawSettings !== "object" || Array.isArray(rawSettings)) {
7890
+ continue;
7891
+ }
7892
+ const settings = rawSettings;
7893
+ const bundleId = buildSetting(settings, "PRODUCT_BUNDLE_IDENTIFIER");
7894
+ if (!bundleId || buildSetting(settings, "CODE_SIGNING_ALLOWED") === "NO") {
7895
+ continue;
7896
+ }
7897
+ const productType = buildSetting(settings, "PRODUCT_TYPE") ?? "";
7898
+ if (productType && !requiresProvisioningProfile(productType)) {
7899
+ continue;
7900
+ }
7901
+ const target2 = typeof record.target === "string" && record.target.trim() || bundleId;
7902
+ const requirement = {
7903
+ bundleId,
7904
+ name: buildSetting(settings, "PRODUCT_NAME") ?? buildSetting(settings, "FULL_PRODUCT_NAME") ?? target2,
7905
+ target: target2,
7906
+ platform: signingPlatform(settings),
7907
+ teamId: buildSetting(settings, "DEVELOPMENT_TEAM"),
7908
+ provisioningProfileSpecifier: buildSetting(settings, "PROVISIONING_PROFILE_SPECIFIER") ?? buildSetting(settings, "PROVISIONING_PROFILE")
7909
+ };
7910
+ const existing = requirements.get(bundleId);
7911
+ if (!existing || !existing.provisioningProfileSpecifier && requirement.provisioningProfileSpecifier) {
7912
+ requirements.set(bundleId, requirement);
7913
+ }
7914
+ }
7915
+ return [...requirements.values()].sort(
7916
+ (left, right) => left.name.localeCompare(right.name)
7917
+ );
7918
+ }
7919
+ function mergeSigningRequirements(requirements) {
7920
+ const merged = /* @__PURE__ */ new Map();
7921
+ for (const requirement of requirements) {
7922
+ const existing = merged.get(requirement.bundleId);
7923
+ if (!existing || !existing.provisioningProfileSpecifier && requirement.provisioningProfileSpecifier) {
7924
+ merged.set(requirement.bundleId, requirement);
7925
+ }
7926
+ }
7927
+ return [...merged.values()].sort(
7928
+ (left, right) => left.name.localeCompare(right.name)
7929
+ );
7930
+ }
7931
+ async function dependentSigningRequirements(source, absolutePath, folder, rootTargetNames, configuration, timeoutMs, signal) {
7932
+ const projects = source.kind === "PROJECT" ? [absolutePath] : source.kind === "WORKSPACE" ? await workspaceProjectPaths(absolutePath, folder) : [];
7933
+ const targets = [];
7934
+ for (const project of projects.slice(0, 50)) {
7935
+ const converted = await command2(
7936
+ "plutil",
7937
+ ["-convert", "json", "-o", "-", join7(project, "project.pbxproj")],
7938
+ Math.min(timeoutMs, 15e3),
7939
+ signal,
7940
+ folder
7941
+ );
7942
+ if (converted.exitCode !== 0) continue;
7943
+ const names = dependentSigningTargetNamesFromPbxProject(
7944
+ parseJson(converted.stdout, "Xcode project graph"),
7945
+ rootTargetNames
7946
+ );
7947
+ targets.push(...names.map((name) => ({ project, name })));
7948
+ }
7949
+ const requirements = [];
7950
+ for (const target2 of targets.slice(0, 50)) {
7951
+ const result = await command2(
7952
+ "xcrun",
7953
+ [
7954
+ "xcodebuild",
7955
+ "-project",
7956
+ target2.project,
7957
+ "-target",
7958
+ target2.name,
7959
+ "-configuration",
7960
+ configuration,
7961
+ "-showBuildSettings",
7962
+ "-json"
7963
+ ],
7964
+ Math.min(timeoutMs, 6e4),
7965
+ signal,
7966
+ folder
7967
+ );
7968
+ if (result.exitCode !== 0) continue;
7969
+ try {
7970
+ requirements.push(
7971
+ ...signingRequirementsFromBuildSettings(JSON.parse(result.stdout))
7972
+ );
7973
+ } catch {
7974
+ }
7975
+ }
7976
+ return requirements;
7977
+ }
7978
+ async function inspectSigningRequirements(source, absolutePath, folder, scheme, configuration, timeoutMs, signal) {
7979
+ if (!scheme || !configuration) return [];
7980
+ const result = requireSuccess3(
7981
+ await command2(
7982
+ "xcrun",
7983
+ [
7984
+ "xcodebuild",
7985
+ ...sourceArguments(source, absolutePath),
7986
+ "-scheme",
7987
+ scheme,
7988
+ "-configuration",
7989
+ configuration,
7990
+ "-destination",
7991
+ "generic/platform=iOS",
7992
+ "-showBuildSettings",
7993
+ "-json"
7994
+ ],
7995
+ Math.min(timeoutMs, 6e4),
7996
+ signal,
7997
+ folder
7998
+ ),
7999
+ "Could not inspect signing requirements"
8000
+ );
8001
+ try {
8002
+ const direct = signingRequirementsFromBuildSettings(
8003
+ JSON.parse(result.stdout)
8004
+ );
8005
+ const dependent = await dependentSigningRequirements(
8006
+ source,
8007
+ absolutePath,
8008
+ folder,
8009
+ direct.map((requirement) => requirement.target),
8010
+ configuration,
8011
+ timeoutMs,
8012
+ signal
8013
+ );
8014
+ return mergeSigningRequirements([...direct, ...dependent]);
8015
+ } catch (error) {
8016
+ throw new Error(
8017
+ `Could not parse Xcode signing requirements: ${cleanError3(error)}`
8018
+ );
8019
+ }
8020
+ }
7387
8021
  var discoverBuildSources = async (payload, timeoutMs, signal) => {
7388
8022
  const input = parseBuildSourceDiscoverPayload(payload);
7389
8023
  const folder = await validateWorktree2(input, timeoutMs, signal);
7390
8024
  return {
7391
- ...successfulProcess5,
8025
+ ...successfulProcess6,
7392
8026
  sources: await discoverSourcesInFolder(folder)
7393
8027
  };
7394
8028
  };
@@ -7402,11 +8036,8 @@ var parseBuildSourceMetadata = async (payload, timeoutMs, signal) => {
7402
8036
  ]);
7403
8037
  const metadata = metadataFromList(list);
7404
8038
  const configurations = input.source.kind === "PACKAGE" ? ["Debug", "Release"] : input.source.kind === "WORKSPACE" && metadata.configurations.length === 0 ? await workspaceConfigurations(absolutePath, folder, timeoutMs, signal) : metadata.configurations;
7405
- return {
7406
- ...successfulProcess5,
7407
- schemes: uniqueSorted(metadata.schemes),
7408
- configurations: uniqueSorted(configurations),
7409
- testPlans: await testPlans(
8039
+ const [plans, signingRequirements] = await Promise.all([
8040
+ testPlans(
7410
8041
  input.source,
7411
8042
  absolutePath,
7412
8043
  folder,
@@ -7414,6 +8045,22 @@ var parseBuildSourceMetadata = async (payload, timeoutMs, signal) => {
7414
8045
  timeoutMs,
7415
8046
  signal
7416
8047
  ),
8048
+ inspectSigningRequirements(
8049
+ input.source,
8050
+ absolutePath,
8051
+ folder,
8052
+ input.scheme,
8053
+ input.configuration,
8054
+ timeoutMs,
8055
+ signal
8056
+ )
8057
+ ]);
8058
+ return {
8059
+ ...successfulProcess6,
8060
+ schemes: uniqueSorted(metadata.schemes),
8061
+ configurations: uniqueSorted(configurations),
8062
+ testPlans: plans,
8063
+ signingRequirements,
7417
8064
  xcodeVersion: version.exitCode === 0 ? version.stdout.trim().replace(/\n+/g, " \xB7 ") : null,
7418
8065
  headSha: input.headSha
7419
8066
  };
@@ -7524,7 +8171,7 @@ function genericBuildDestinations(action) {
7524
8171
  ];
7525
8172
  }
7526
8173
  async function listPhysicalDevices(timeoutMs, signal) {
7527
- const directory = await mkdtemp2(join7(tmpdir2(), "ade-devices-"));
8174
+ const directory = await mkdtemp3(join7(tmpdir3(), "ade-devices-"));
7528
8175
  const output = join7(directory, "devices.json");
7529
8176
  try {
7530
8177
  const result = await command2(
@@ -7543,9 +8190,9 @@ async function listPhysicalDevices(timeoutMs, signal) {
7543
8190
  signal
7544
8191
  );
7545
8192
  if (result.exitCode !== 0) return [];
7546
- return physicalDestinations(JSON.parse(await readFile4(output, "utf8")));
8193
+ return physicalDestinations(JSON.parse(await readFile5(output, "utf8")));
7547
8194
  } finally {
7548
- await rm4(directory, { recursive: true, force: true });
8195
+ await rm5(directory, { recursive: true, force: true });
7549
8196
  }
7550
8197
  }
7551
8198
  var inspectBuildDestinations = async (payload, timeoutMs, signal) => {
@@ -7580,7 +8227,7 @@ var inspectBuildDestinations = async (payload, timeoutMs, signal) => {
7580
8227
  listPhysicalDevices(timeoutMs, signal)
7581
8228
  ]);
7582
8229
  return {
7583
- ...successfulProcess5,
8230
+ ...successfulProcess6,
7584
8231
  destinations: [
7585
8232
  ...genericBuildDestinations(input.action),
7586
8233
  ...simulators.exitCode === 0 ? simulatorDestinations(JSON.parse(simulators.stdout)) : [],
@@ -7601,12 +8248,12 @@ var inspectBuildRunDestinations = async (payload, timeoutMs, signal) => {
7601
8248
  );
7602
8249
  requireSuccess3(simulators, "Could not inspect available simulators");
7603
8250
  return {
7604
- ...successfulProcess5,
8251
+ ...successfulProcess6,
7605
8252
  destinations: simulatorDestinations(JSON.parse(simulators.stdout))
7606
8253
  };
7607
8254
  }
7608
8255
  return {
7609
- ...successfulProcess5,
8256
+ ...successfulProcess6,
7610
8257
  destinations: await listPhysicalDevices(timeoutMs, signal)
7611
8258
  };
7612
8259
  };
@@ -8025,16 +8672,16 @@ async function runHook(options) {
8025
8672
  const log = join7(directory, `${prefix}.log`);
8026
8673
  const started = Date.now();
8027
8674
  try {
8028
- await mkdir3(directory, { recursive: true, mode: 448 });
8029
- await writeFile3(file, `${options.source}
8675
+ await mkdir4(directory, { recursive: true, mode: 448 });
8676
+ await writeFile4(file, `${options.source}
8030
8677
  `, { mode: 384 });
8031
- await writeFile3(
8678
+ await writeFile4(
8032
8679
  options.contextPath,
8033
8680
  `${JSON.stringify(options.hookContext, null, 2)}
8034
8681
  `,
8035
8682
  { mode: 384 }
8036
8683
  );
8037
- await writeFile3(
8684
+ await writeFile4(
8038
8685
  runner,
8039
8686
  `import { readFile } from "node:fs/promises";
8040
8687
  const hookModule = await import(${JSON.stringify(`./${basename4(file)}`)});
@@ -8312,7 +8959,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8312
8959
  const resultBundle = join7(input.artifactDirectory, "result.xcresult");
8313
8960
  const filename = kind === "TEST_RESULTS" ? "test-results.json" : "code-coverage.json";
8314
8961
  const destination = join7(input.artifactDirectory, filename);
8315
- const temporary = `${destination}.tmp-${randomUUID2()}`;
8962
+ const temporary = `${destination}.tmp-${randomUUID3()}`;
8316
8963
  try {
8317
8964
  if (!await pathExists(resultBundle)) {
8318
8965
  throw new Error("The build result bundle is unavailable");
@@ -8339,7 +8986,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8339
8986
  ),
8340
8987
  `Could not generate ${filename}`
8341
8988
  );
8342
- const serialized = await readFile4(temporary, "utf8");
8989
+ const serialized = await readFile5(temporary, "utf8");
8343
8990
  const parsed = JSON.parse(serialized);
8344
8991
  const normalized = kind === "TEST_RESULTS" ? normalizeTestResults(parsed) : normalizeCoverage(parsed);
8345
8992
  await rename3(temporary, destination);
@@ -8355,7 +9002,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8355
9002
  error: null
8356
9003
  };
8357
9004
  } catch (error) {
8358
- await rm4(temporary, { force: true });
9005
+ await rm5(temporary, { force: true });
8359
9006
  return {
8360
9007
  kind,
8361
9008
  status: "FAILED",
@@ -8446,7 +9093,7 @@ async function snapshotCoverageChanges(input, folder, timeoutMs, signal) {
8446
9093
  const types = changeTypesFromStatus(status2.stdout);
8447
9094
  for (const path of untracked.stdout.split("\0").filter(Boolean)) {
8448
9095
  try {
8449
- const contents = await readFile4(join7(folder, path));
9096
+ const contents = await readFile5(join7(folder, path));
8450
9097
  if (contents.includes(0)) continue;
8451
9098
  const lineCount = contents.length ? contents.toString("utf8").split("\n").length - (contents.toString("utf8").endsWith("\n") ? 1 : 0) : 0;
8452
9099
  lines.set(
@@ -8482,7 +9129,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8482
9129
  if (coveragePath && change.lines.length) {
8483
9130
  const temporary2 = join7(
8484
9131
  input.artifactDirectory,
8485
- `.changed-coverage-${randomUUID2()}.json`
9132
+ `.changed-coverage-${randomUUID3()}.json`
8486
9133
  );
8487
9134
  try {
8488
9135
  const result = await commandToFile(
@@ -8504,7 +9151,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8504
9151
  );
8505
9152
  if (result.exitCode === 0 && !result.cancelled && !result.timedOut) {
8506
9153
  const parsed = jsonObject(
8507
- JSON.parse(await readFile4(temporary2, "utf8"))
9154
+ JSON.parse(await readFile5(temporary2, "utf8"))
8508
9155
  );
8509
9156
  const lineData = parsed?.[coveragePath];
8510
9157
  if (Array.isArray(lineData)) {
@@ -8521,7 +9168,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8521
9168
  }
8522
9169
  }
8523
9170
  } finally {
8524
- await rm4(temporary2, { force: true });
9171
+ await rm5(temporary2, { force: true });
8525
9172
  }
8526
9173
  }
8527
9174
  changedCoveredLines += covered;
@@ -8542,8 +9189,8 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8542
9189
  };
8543
9190
  const data = { ...report.data, changedFiles };
8544
9191
  const destination = join7(input.artifactDirectory, "worktree-coverage.json");
8545
- const temporary = `${destination}.tmp-${randomUUID2()}`;
8546
- await writeFile3(temporary, JSON.stringify({ summary, data }, null, 2), {
9192
+ const temporary = `${destination}.tmp-${randomUUID3()}`;
9193
+ await writeFile4(temporary, JSON.stringify({ summary, data }, null, 2), {
8547
9194
  mode: 384
8548
9195
  });
8549
9196
  await rename3(temporary, destination);
@@ -8659,8 +9306,8 @@ async function captureArtifacts(input, folder, signal, includeProducts = true) {
8659
9306
  if (source && await pathExists(source)) {
8660
9307
  const productDirectory = join7(input.artifactDirectory, "products");
8661
9308
  const destination = join7(productDirectory, basename4(source));
8662
- await mkdir3(productDirectory, { recursive: true, mode: 448 });
8663
- await rm4(destination, { recursive: true, force: true });
9309
+ await mkdir4(productDirectory, { recursive: true, mode: 448 });
9310
+ await rm5(destination, { recursive: true, force: true });
8664
9311
  await cp(source, destination, {
8665
9312
  recursive: true,
8666
9313
  preserveTimestamps: true
@@ -8725,7 +9372,7 @@ var runIosBuild = async (payload, timeoutMs, signal, onLog, context) => {
8725
9372
  Math.min(timeoutMs, 6e4),
8726
9373
  signal
8727
9374
  );
8728
- await mkdir3(input.artifactDirectory, { recursive: true, mode: 448 });
9375
+ await mkdir4(input.artifactDirectory, { recursive: true, mode: 448 });
8729
9376
  const rawLog = join7(input.artifactDirectory, "build.log");
8730
9377
  const logger = new BuildLogger(input.buildId, context, rawLog, process.env);
8731
9378
  try {
@@ -8967,7 +9614,7 @@ var generateIosBuildReport = async (payload, timeoutMs, signal, onLog) => {
8967
9614
  if (!isAbsolute4(input.artifactDirectory) || basename4(input.artifactDirectory) !== input.buildId) {
8968
9615
  throw new Error("Build artifact directory is invalid");
8969
9616
  }
8970
- if (signal.aborted) return { ...successfulProcess5, cancelled: true };
9617
+ if (signal.aborted) return { ...successfulProcess6, cancelled: true };
8971
9618
  const report = await writeJsonReport(
8972
9619
  input,
8973
9620
  input.reportKind,
@@ -8981,22 +9628,22 @@ var generateIosBuildReport = async (payload, timeoutMs, signal, onLog) => {
8981
9628
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
8982
9629
  });
8983
9630
  return {
8984
- ...successfulProcess5,
9631
+ ...successfulProcess6,
8985
9632
  report,
8986
9633
  artifacts: report.artifact ? [report.artifact] : []
8987
9634
  };
8988
9635
  };
8989
9636
  var deleteIosBuild = async (payload, _timeoutMs, signal, onLog) => {
8990
9637
  const input = parseBuildDeletePayload(payload);
8991
- if (signal.aborted) return { ...successfulProcess5, cancelled: true };
8992
- await rm4(input.artifactDirectory, { recursive: true, force: true });
9638
+ if (signal.aborted) return { ...successfulProcess6, cancelled: true };
9639
+ await rm5(input.artifactDirectory, { recursive: true, force: true });
8993
9640
  await onLog({
8994
9641
  sequence: 0,
8995
9642
  stream: "SYSTEM",
8996
9643
  message: `Deleted build folder ${input.artifactDirectory}`,
8997
9644
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
8998
9645
  });
8999
- return successfulProcess5;
9646
+ return successfulProcess6;
9000
9647
  };
9001
9648
  var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context) => {
9002
9649
  const input = parseBuildArtifactDownloadPayload(payload);
@@ -9019,8 +9666,8 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
9019
9666
  try {
9020
9667
  if (information.isDirectory()) {
9021
9668
  temporaryArchive = join7(
9022
- tmpdir2(),
9023
- `ade-build-artifact-${randomUUID2()}.tar.gz`
9669
+ tmpdir3(),
9670
+ `ade-build-artifact-${randomUUID3()}.tar.gz`
9024
9671
  );
9025
9672
  requireSuccess3(
9026
9673
  await command2(
@@ -9049,10 +9696,10 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
9049
9696
  filename,
9050
9697
  contentType
9051
9698
  });
9052
- return successfulProcess5;
9699
+ return successfulProcess6;
9053
9700
  } finally {
9054
9701
  if (temporaryArchive) {
9055
- await rm4(temporaryArchive, { force: true });
9702
+ await rm5(temporaryArchive, { force: true });
9056
9703
  }
9057
9704
  }
9058
9705
  };
@@ -9089,7 +9736,7 @@ var deployIosBuild = async (payload, timeoutMs, signal, _onLog, context) => {
9089
9736
  throw new Error("Runnable app artifact is missing");
9090
9737
  }
9091
9738
  const deploymentsDirectory = join7(input.artifactDirectory, "deployments");
9092
- await mkdir3(deploymentsDirectory, { recursive: true, mode: 448 });
9739
+ await mkdir4(deploymentsDirectory, { recursive: true, mode: 448 });
9093
9740
  const logger = new BuildLogger(
9094
9741
  input.buildId,
9095
9742
  context,
@@ -9104,7 +9751,7 @@ var deployIosBuild = async (payload, timeoutMs, signal, _onLog, context) => {
9104
9751
  "deployments",
9105
9752
  deployment.id
9106
9753
  );
9107
- await mkdir3(directory, { recursive: true, mode: 448 });
9754
+ await mkdir4(directory, { recursive: true, mode: 448 });
9108
9755
  const logPath = join7(directory, "deployment.log");
9109
9756
  const started = Date.now();
9110
9757
  let failure = null;
@@ -9288,8 +9935,16 @@ function exportPlist(settings) {
9288
9935
  signingStyle: settings.signingStyle.toLowerCase(),
9289
9936
  uploadSymbols: settings.uploadSymbols,
9290
9937
  manageAppVersionAndBuildNumber: settings.manageAppVersionAndBuildNumber,
9291
- testFlightInternalTestingOnly: settings.testFlightInternalTestingOnly
9938
+ testFlightInternalTestingOnly: settings.testFlightInternalTestingOnly,
9939
+ stripSwiftSymbols: settings.stripSwiftSymbols
9292
9940
  };
9941
+ if (settings.thinning) values.thinning = settings.thinning;
9942
+ if (settings.iCloudContainerEnvironment) {
9943
+ values.iCloudContainerEnvironment = settings.iCloudContainerEnvironment;
9944
+ }
9945
+ if (settings.distributionBundleIdentifier) {
9946
+ values.distributionBundleIdentifier = settings.distributionBundleIdentifier;
9947
+ }
9293
9948
  if (settings.teamId) values.teamID = settings.teamId;
9294
9949
  if (settings.signingCertificate)
9295
9950
  values.signingCertificate = settings.signingCertificate;
@@ -9317,10 +9972,10 @@ var exportIosArchive = async (payload, timeoutMs, signal, _onLog, context) => {
9317
9972
  "exports",
9318
9973
  input.exportId
9319
9974
  );
9320
- await mkdir3(exportDirectory, { recursive: true, mode: 448 });
9975
+ await mkdir4(exportDirectory, { recursive: true, mode: 448 });
9321
9976
  const plistPath = join7(exportDirectory, "ExportOptions.plist");
9322
9977
  const logPath = join7(exportDirectory, "export.log");
9323
- await writeFile3(plistPath, exportPlist(input.settings), { mode: 384 });
9978
+ await writeFile4(plistPath, exportPlist(input.settings), { mode: 384 });
9324
9979
  const logger = new BuildLogger(input.buildId, context, logPath, process.env);
9325
9980
  try {
9326
9981
  const result = await runLoggedCommand({
@@ -9412,7 +10067,13 @@ var handlers = {
9412
10067
  [IOS_EXPORT_JOB_KIND]: exportIosArchive,
9413
10068
  [IOS_TEST_RESULTS_JOB_KIND]: generateIosBuildReport,
9414
10069
  [IOS_COVERAGE_REPORT_JOB_KIND]: generateIosBuildReport,
9415
- [IOS_SIGNING_INSPECT_JOB_KIND]: inspectIosSigning
10070
+ [IOS_SIGNING_INSPECT_JOB_KIND]: inspectIosSigning,
10071
+ [SIGNING_ASSETS_SCAN_JOB_KIND]: scanSigningAssets,
10072
+ [SIGNING_PROFILE_READ_JOB_KIND]: readSigningProfile,
10073
+ [SIGNING_PROFILE_INSTALL_JOB_KIND]: installSigningProfile,
10074
+ [SIGNING_PROFILE_DELETE_JOB_KIND]: deleteSigningProfile,
10075
+ [SIGNING_IDENTITY_IMPORT_JOB_KIND]: importSigningIdentity,
10076
+ [SIGNING_IDENTITY_DELETE_JOB_KIND]: deleteSigningIdentity
9416
10077
  };
9417
10078
 
9418
10079
  // src/repository-coordinator.ts
@@ -9491,7 +10152,8 @@ var JobExecutor = class {
9491
10152
  reportWorktreeActivity: (input) => this.client.reportWorktreeActivity(input),
9492
10153
  reportBuildProgress: (input) => this.client.reportBuildProgress(input),
9493
10154
  appendBuildLogs: (buildId, events) => this.client.appendBuildLogs(buildId, events),
9494
- uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input)
10155
+ uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input),
10156
+ claimSigningSecretTransfer: (transferId) => this.client.claimSigningSecretTransfer(transferId)
9495
10157
  }
9496
10158
  );
9497
10159
  const codebaseId = claimed.payload && typeof claimed.payload === "object" && !Array.isArray(claimed.payload) && typeof claimed.payload.codebaseId === "string" ? String(claimed.payload.codebaseId) : null;