@m8t-stack/cli 0.2.22 → 0.2.23

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.
package/README.md CHANGED
@@ -17,10 +17,10 @@ It's the operator's day-2 tool for the cloud platform — the successor to the o
17
17
  npm install -g @m8t-stack/cli
18
18
 
19
19
  # Homebrew (macOS / Linux)
20
- brew install m8t-run/tap/m8t
20
+ brew install m8t-labs/tap/m8t
21
21
 
22
22
  # Scoop (Windows)
23
- scoop bucket add m8t https://github.com/m8t-run/scoop-bucket
23
+ scoop bucket add m8t https://github.com/m8t-labs/scoop-bucket
24
24
  scoop install m8t
25
25
 
26
26
  # Verify
@@ -115,7 +115,7 @@ Provisions (or updates) the gateway/webapp stack via Bicep — the successor to
115
115
  m8t deploy --client-id <appId> --image-ref <acr-or-ghcr-ref> --location <region>
116
116
  ```
117
117
 
118
- Key flags: `--client-id <appId>` (reuse an existing app reg + skip **all** Microsoft Graph writes), `--image-ref <ref>` (full image ref; default `ghcr.io/m8t-run/m8t:latest` — pass an `*.azurecr.io/...` ref for ACR images), `--resource-group` (default `rg-m8t-stack`), `--location`, `--suffix`, `--foundry-endpoint`, `--foundry-resource-id`.
118
+ Key flags: `--client-id <appId>` (reuse an existing app reg + skip **all** Microsoft Graph writes), `--image-ref <ref>` (full image ref; default `ghcr.io/m8t-labs/m8t:latest` — pass an `*.azurecr.io/...` ref for ACR images), `--resource-group` (default `rg-m8t-stack`), `--location`, `--suffix`, `--foundry-endpoint`, `--foundry-resource-id`.
119
119
 
120
120
  > ⚠️ `m8t deploy` is **declarative** — it makes the live stack match the Bicep template. If a deployment was hand-modified after provisioning (e.g. switched to a private-ACR image with a UserAssigned pull identity), re-running the bicep can revert those changes. **Preview with `az deployment group create --what-if` before applying against a live stack.**
121
121
 
package/dist/cli.js CHANGED
@@ -1231,7 +1231,7 @@ var init_enable_hosted_brain = __esm({
1231
1231
  import { Builtins, Cli } from "clipanion";
1232
1232
 
1233
1233
  // src/lib/package-version.ts
1234
- var CLI_VERSION = "0.2.22";
1234
+ var CLI_VERSION = "0.2.23";
1235
1235
 
1236
1236
  // src/lib/render-error.ts
1237
1237
  init_errors();
@@ -11481,6 +11481,31 @@ import { DefaultAzureCredential } from "@azure/identity";
11481
11481
  // src/lib/az.ts
11482
11482
  init_errors();
11483
11483
  import { spawn } from "child_process";
11484
+ var SECRET_VALUE_FLAGS = /* @__PURE__ */ new Set(["--secure-environment-variables"]);
11485
+ var SECRET_KEY_RE = /(pem|secret|token|password|passwd|pwd|credential|private[-_]?key)/i;
11486
+ function redactAzArgs(args) {
11487
+ const out = [];
11488
+ let secretFlagActive = false;
11489
+ for (const arg of args) {
11490
+ if (arg.startsWith("-")) {
11491
+ secretFlagActive = SECRET_VALUE_FLAGS.has(arg);
11492
+ out.push(arg);
11493
+ continue;
11494
+ }
11495
+ const eq = arg.indexOf("=");
11496
+ const key2 = eq > 0 ? arg.slice(0, eq) : "";
11497
+ if (secretFlagActive) {
11498
+ out.push(key2 ? `${key2}=[REDACTED]` : "[REDACTED]");
11499
+ continue;
11500
+ }
11501
+ if (key2 && SECRET_KEY_RE.test(key2)) {
11502
+ out.push(`${key2}=[REDACTED]`);
11503
+ continue;
11504
+ }
11505
+ out.push(arg);
11506
+ }
11507
+ return out;
11508
+ }
11484
11509
  function runAz(args) {
11485
11510
  return new Promise((resolve3, reject) => {
11486
11511
  const proc = spawn("az", args, { stdio: ["ignore", "pipe", "pipe"] });
@@ -11517,7 +11542,7 @@ function runAz(args) {
11517
11542
  reject(
11518
11543
  new LocalCliError({
11519
11544
  code: "AZ_COMMAND_FAILED",
11520
- message: `'az ${args.join(" ")}' failed: ${errString.trim()}`
11545
+ message: `'az ${redactAzArgs(args).join(" ")}' failed: ${errString.trim()}`
11521
11546
  })
11522
11547
  );
11523
11548
  return;
@@ -16900,7 +16925,7 @@ var SIZE_PRESETS = {
16900
16925
  medium: { cpu: "1", memory: "2Gi" },
16901
16926
  large: { cpu: "2", memory: "4Gi" }
16902
16927
  };
16903
- var DEFAULT_REGISTRY = "ghcr.io/m8t-run";
16928
+ var DEFAULT_REGISTRY = "ghcr.io/m8t-labs";
16904
16929
  var DEFAULT_IMAGE = "m8t-coding-agent";
16905
16930
  var DEFAULT_TAG = "v0.1.0";
16906
16931
  var DEFAULT_MODEL = "gpt-4.1-mini";
@@ -16909,7 +16934,7 @@ var CoderDeployCommand = class extends M8tCommand {
16909
16934
  static paths = [["coder", "deploy"]];
16910
16935
  static usage = Command28.Usage({
16911
16936
  description: "Deploy the curated coding agent as a hosted Foundry worker.",
16912
- details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-run/m8t-coding-agent). Post-2026-06-25 Foundry projects require an authenticated pull, so a public image is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 a server-side copy, no local build) and the agent is deployed from that ACR ref. Re-running with a newer --image-tag imports the new tag and rolls out a new agent version \u2014 that is how you update a worker's image. Override --image with a private ACR ref to bring your own registry.",
16937
+ details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-labs/m8t-coding-agent). Post-2026-06-25 Foundry projects require an authenticated pull, so a public image is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 a server-side copy, no local build) and the agent is deployed from that ACR ref. Re-running with a newer --image-tag imports the new tag and rolls out a new agent version \u2014 that is how you update a worker's image. Override --image with a private ACR ref to bring your own registry.",
16913
16938
  examples: [
16914
16939
  ["Deploy a coder with defaults", "$0 coder deploy my-coder"],
16915
16940
  ["Larger sandbox + a custom model", "$0 coder deploy my-coder --size large --model-deployment gpt-4.1"],
@@ -17296,7 +17321,7 @@ var SIZE_PRESETS2 = {
17296
17321
  medium: { cpu: "1", memory: "2Gi" },
17297
17322
  large: { cpu: "2", memory: "4Gi" }
17298
17323
  };
17299
- var DEFAULT_REGISTRY2 = "ghcr.io/m8t-run";
17324
+ var DEFAULT_REGISTRY2 = "ghcr.io/m8t-labs";
17300
17325
  var DEFAULT_IMAGE2 = "m8t-azure-executor";
17301
17326
  var DEFAULT_TAG2 = "v0.1.0";
17302
17327
  var DEFAULT_MODEL2 = "gpt-5-mini";
@@ -17305,11 +17330,11 @@ var AzureExecDeployCommand = class extends M8tCommand {
17305
17330
  static paths = [["azure-exec", "deploy"]];
17306
17331
  static usage = Command30.Usage({
17307
17332
  description: "Deploy the Azure executor as a hosted Foundry worker (az CLI + tiered ops).",
17308
- details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-run/m8t-azure-executor \u2014 no local build needed), grants its identity Foundry User + Contributor (at --scope) + Key Vault Secrets User (brain KV), polls to active, and a2a-enables it as a target. Override with --image/--image-tag for a bring-your-own-registry image (e.g. a private ACR ref, which must be pushed first). Contributor scope is REQUIRED \u2014 pass --scope or --resource-group. Pass --grant-access-admin to additionally grant User Access Administrator (enables human-approved Tier-2 role/delete ops). Post-2026-06-25 Foundry projects require an authenticated pull, so the public image (default ghcr.io/m8t-run/m8t-azure-executor) is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 server-side, no local build) and deployed from that ACR ref; re-running with a newer --image-tag updates the image.",
17333
+ details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-labs/m8t-azure-executor \u2014 no local build needed), grants its identity Foundry User + Contributor (at --scope) + Key Vault Secrets User (brain KV), polls to active, and a2a-enables it as a target. Override with --image/--image-tag for a bring-your-own-registry image (e.g. a private ACR ref, which must be pushed first). Contributor scope is REQUIRED \u2014 pass --scope or --resource-group. Pass --grant-access-admin to additionally grant User Access Administrator (enables human-approved Tier-2 role/delete ops). Post-2026-06-25 Foundry projects require an authenticated pull, so the public image (default ghcr.io/m8t-labs/m8t-azure-executor) is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 server-side, no local build) and deployed from that ACR ref; re-running with a newer --image-tag updates the image.",
17309
17334
  examples: [
17310
17335
  [
17311
17336
  "Deploy scoped to a resource group",
17312
- "$0 azure-exec deploy azexec --resource-group rg-test --brain m8t-run/azure-exec-smoke-brain --gateway-url https://<gw>/api/a2a/mcp"
17337
+ "$0 azure-exec deploy azexec --resource-group rg-test --brain m8t-labs/azure-exec-smoke-brain --gateway-url https://<gw>/api/a2a/mcp"
17313
17338
  ]
17314
17339
  ]
17315
17340
  });
@@ -17341,7 +17366,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
17341
17366
  throw new LocalCliError({
17342
17367
  code: "USAGE",
17343
17368
  message: "--brain owner/repo is required (the executor delivers proof to a brain).",
17344
- hint: "Example: --brain m8t-run/azure-exec-smoke-brain"
17369
+ hint: "Example: --brain m8t-labs/azure-exec-smoke-brain"
17345
17370
  });
17346
17371
  }
17347
17372
  const size = (this.size ?? "large").toLowerCase();
@@ -17573,7 +17598,7 @@ import { DefaultAzureCredential as DefaultAzureCredential16 } from "@azure/ident
17573
17598
 
17574
17599
  // src/lib/platform-update.ts
17575
17600
  init_errors();
17576
- var DEFAULT_IMAGE_REPO = "ghcr.io/m8t-run/m8t";
17601
+ var DEFAULT_IMAGE_REPO = "ghcr.io/m8t-labs/m8t";
17577
17602
  function parseImageRef2(ref) {
17578
17603
  const lastColon = ref.lastIndexOf(":");
17579
17604
  const lastSlash = ref.lastIndexOf("/");
@@ -17806,13 +17831,13 @@ function entityToStamp(e) {
17806
17831
  }
17807
17832
 
17808
17833
  // ../../packages/platform-release/dist/esm/channel-url.js
17809
- var CHANNEL_LATEST_URL = "https://github.com/m8t-run/m8t/releases/latest/download/manifest.json";
17834
+ var CHANNEL_LATEST_URL = "https://github.com/m8t-labs/m8t/releases/latest/download/manifest.json";
17810
17835
  function platformTag(version) {
17811
17836
  const bare = version.trim().replace(/^platform-/, "").replace(/^v/, "");
17812
17837
  return `platform-v${bare}`;
17813
17838
  }
17814
17839
  function channelUrlForVersion(version) {
17815
- return `https://github.com/m8t-run/m8t/releases/download/${platformTag(version)}/manifest.json`;
17840
+ return `https://github.com/m8t-labs/m8t/releases/download/${platformTag(version)}/manifest.json`;
17816
17841
  }
17817
17842
 
17818
17843
  // ../../packages/platform-release/dist/esm/apply-request.js
@@ -17902,7 +17927,7 @@ import * as os8 from "os";
17902
17927
  import * as path19 from "path";
17903
17928
  import { execFileSync as execFileSync2 } from "child_process";
17904
17929
  init_errors();
17905
- var OWNER_REPO = "m8t-run/m8t";
17930
+ var OWNER_REPO = "m8t-labs/m8t";
17906
17931
  function parseTreeResponse(body) {
17907
17932
  const map = /* @__PURE__ */ new Map();
17908
17933
  for (const e of body.tree ?? []) if (e.type === "tree") map.set(e.path, e.sha);
@@ -20750,7 +20775,7 @@ function classifyWhatIf(changes) {
20750
20775
  }
20751
20776
 
20752
20777
  // src/commands/deploy.ts
20753
- var DEFAULT_IMAGE_REF = "ghcr.io/m8t-run/m8t:latest";
20778
+ var DEFAULT_IMAGE_REF = "ghcr.io/m8t-labs/m8t:latest";
20754
20779
  var DeployCommand = class extends M8tCommand {
20755
20780
  static paths = [["deploy"]];
20756
20781
  static usage = Command36.Usage({
@@ -21151,7 +21176,7 @@ function resolveJudgeDeployment(flag, env) {
21151
21176
  warning: "no --deployment and no $EXAM_JUDGE_DEPLOYMENT \u2014 falling back to gpt-5-mini as the judge. Name the DISTINCT judge deployment before any blessing/calibration run (DESIGN \xA75.5)."
21152
21177
  };
21153
21178
  }
21154
- var BRAIN_REPO_MARKERS = ["m8t-run/", "/azure-advisor-brain", "/stacey-brain", "exam-arm-"];
21179
+ var BRAIN_REPO_MARKERS = ["m8t-labs/", "/azure-advisor-brain", "/stacey-brain", "exam-arm-"];
21155
21180
  function assertOutNotInBrainRepo(out) {
21156
21181
  if (BRAIN_REPO_MARKERS.some((m) => out.includes(m))) {
21157
21182
  throw new LocalCliError({
@@ -25605,8 +25630,8 @@ async function writeBootstrapState(state, home = os13.homedir()) {
25605
25630
 
25606
25631
  // src/commands/bootstrap/launch.ts
25607
25632
  var DEFAULT_RG = "rg-m8t-stack";
25608
- var DEFAULT_INSTALLER = "ghcr.io/m8t-run/m8t-installer";
25609
- var DEFAULT_INSTALLER_TAG = "v0.1.0";
25633
+ var DEFAULT_INSTALLER = "ghcr.io/m8t-labs/m8t-installer";
25634
+ var DEFAULT_INSTALLER_TAG = "v0.1.30";
25610
25635
  var ACI_NAME = "m8t-installer";
25611
25636
  var MI_NAME = "m8t-installer-mi";
25612
25637
  var BootstrapLaunchCommand = class extends M8tCommand {
@@ -25617,7 +25642,8 @@ var BootstrapLaunchCommand = class extends M8tCommand {
25617
25642
  examples: [
25618
25643
  ["Launch in eastus2", "$0 bootstrap launch --location eastus2"],
25619
25644
  ["BYO app registration", "$0 bootstrap launch --location eastus2 --client-id <appId>"],
25620
- ["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.0"]
25645
+ ["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.30"],
25646
+ ["Override the full installer image ref", "$0 bootstrap launch --location eastus2 --installer-image ghcr.io/m8t-labs/m8t-installer:v0.1.30"]
25621
25647
  ]
25622
25648
  });
25623
25649
  location = Option46.String("--location");
@@ -25625,6 +25651,10 @@ var BootstrapLaunchCommand = class extends M8tCommand {
25625
25651
  clientId = Option46.String("--client-id");
25626
25652
  subscription = Option46.String("--subscription");
25627
25653
  installerTag = Option46.String("--installer-tag");
25654
+ // Full image ref override (registry + repo + tag) — an escape hatch when the
25655
+ // default org/tag is wrong for the current CLI (e.g. a stale published build).
25656
+ // Wins over --installer-tag / the pinned default.
25657
+ installerImage = Option46.String("--installer-image");
25628
25658
  gatewayImageRef = Option46.String("--gateway-image-ref");
25629
25659
  githubAppCreds = Option46.String("--github-app-creds");
25630
25660
  async executeCommand() {
@@ -25635,6 +25665,8 @@ var BootstrapLaunchCommand = class extends M8tCommand {
25635
25665
  const resourceGroup = (typeof this.resourceGroup === "string" ? this.resourceGroup : void 0) ?? DEFAULT_RG;
25636
25666
  const clientIdOpt = typeof this.clientId === "string" ? this.clientId : void 0;
25637
25667
  const installerTag = (typeof this.installerTag === "string" ? this.installerTag : void 0) ?? DEFAULT_INSTALLER_TAG;
25668
+ const installerImageOverride = typeof this.installerImage === "string" ? this.installerImage : void 0;
25669
+ const installerImage = installerImageOverride ?? `${DEFAULT_INSTALLER}:${installerTag}`;
25638
25670
  const gatewayImageRef = typeof this.gatewayImageRef === "string" ? this.gatewayImageRef : void 0;
25639
25671
  const account = await getAzAccount();
25640
25672
  const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
@@ -25685,10 +25717,24 @@ var BootstrapLaunchCommand = class extends M8tCommand {
25685
25717
  out("granting Owner at subscription scope\u2026");
25686
25718
  await grantOwnerAtSubscription({ principalId: mi.principalId, subscriptionId });
25687
25719
  const roleAssignmentIds = await listAssignmentIds({ principalId: mi.principalId, subscriptionId });
25720
+ const saName = deriveStatusSaName(resourceGroup, subscriptionId);
25721
+ await writeBootstrapState({
25722
+ subscriptionId,
25723
+ resourceGroup,
25724
+ location,
25725
+ aciName: ACI_NAME,
25726
+ miName: MI_NAME,
25727
+ miClientId: mi.clientId,
25728
+ miPrincipalId: mi.principalId,
25729
+ roleAssignmentIds,
25730
+ appRegClientId: appReg.clientId,
25731
+ statusSaName: saName,
25732
+ statusBlobUrl: statusBlobUrl(saName),
25733
+ installerTag
25734
+ });
25688
25735
  out("waiting for the installer identity to be usable (role propagation)\u2026");
25689
25736
  const miReady = await waitForMiToken({ clientId: mi.clientId, subscriptionId, onProgress: out });
25690
25737
  if (!miReady) out("identity not confirmed yet \u2014 launching anyway (the installer retries its own login)");
25691
- const saName = deriveStatusSaName(resourceGroup, subscriptionId);
25692
25738
  out("launching the cloud installer (ACI)\u2026");
25693
25739
  await kickInstaller({
25694
25740
  aciName: ACI_NAME,
@@ -25698,25 +25744,11 @@ var BootstrapLaunchCommand = class extends M8tCommand {
25698
25744
  miResourceId: mi.resourceId,
25699
25745
  miClientId: mi.clientId,
25700
25746
  appRegClientId: appReg.clientId,
25701
- image: `${DEFAULT_INSTALLER}:${installerTag}`,
25747
+ image: installerImage,
25702
25748
  gatewayImageRef,
25703
25749
  foundryTracing: "skip",
25704
25750
  githubApp
25705
25751
  });
25706
- await writeBootstrapState({
25707
- subscriptionId,
25708
- resourceGroup,
25709
- location,
25710
- aciName: ACI_NAME,
25711
- miName: MI_NAME,
25712
- miClientId: mi.clientId,
25713
- miPrincipalId: mi.principalId,
25714
- roleAssignmentIds,
25715
- appRegClientId: appReg.clientId,
25716
- statusSaName: saName,
25717
- statusBlobUrl: statusBlobUrl(saName),
25718
- installerTag
25719
- });
25720
25752
  this.context.stdout.write(
25721
25753
  `${colors.success("\u2713")} installer launched in ${colors.field(resourceGroup)} (${location}).
25722
25754
  ${colors.hint("next:")} m8t bootstrap status --watch ${colors.dim("# watch the install to done")}
@@ -25944,24 +25976,43 @@ Found ${String(found.length)} orphaned Owner@sub assignment(s) (dry-run). ${colo
25944
25976
  }
25945
25977
  const state = await readBootstrapState();
25946
25978
  if (!state) {
25947
- throw new LocalCliError({ code: "BOOTSTRAP_NO_STATE", message: "No bootstrap state to reap.", hint: "Nothing to do." });
25979
+ if (this.force === true) {
25980
+ const { subscriptionId: sub } = await getAzAccount();
25981
+ if (!sub) {
25982
+ throw new LocalCliError({ code: "BOOTSTRAP_SWEEP_NO_SUB", message: "No active subscription.", hint: "Run 'az account set --subscription <id>'." });
25983
+ }
25984
+ const found = await sweepOrphanOwnerAssignments({ subscriptionId: sub, execute: true });
25985
+ this.context.stdout.write(
25986
+ found.length === 0 ? `${colors.success("\u2713")} No bootstrap state and no orphaned installer Owner@sub assignments. Nothing to reap.
25987
+ ` : `${colors.success("\u2713")} No bootstrap state found; swept ${String(found.length)} orphaned installer Owner@sub assignment(s).
25988
+ `
25989
+ );
25990
+ return 0;
25991
+ }
25992
+ throw new LocalCliError({
25993
+ code: "BOOTSTRAP_NO_STATE",
25994
+ message: "No bootstrap state to reap.",
25995
+ hint: "Nothing to do. If a launch failed early it may have orphaned an installer Owner@sub grant \u2014 run 'm8t bootstrap reap --force' (or 'm8t bootstrap reap --sweep-orphans --yes') to clean it."
25996
+ });
25948
25997
  }
25949
- const doc = await readStatusBlob({ saName: state.statusSaName, resourceGroup: state.resourceGroup, subscriptionId: state.subscriptionId });
25950
- if (doc.status !== "done" && !(this.force === true)) {
25951
- if (doc.status === "failed") {
25998
+ if (this.force !== true) {
25999
+ const doc = await readStatusBlob({ saName: state.statusSaName, resourceGroup: state.resourceGroup, subscriptionId: state.subscriptionId });
26000
+ if (doc.status !== "done") {
26001
+ if (doc.status === "failed") {
26002
+ throw new LocalCliError({
26003
+ code: "BOOTSTRAP_REAP_FAILED_INSTALL",
26004
+ message: `The install failed at '${doc.error?.phase ?? doc.phase}'. Leaving the installer up for diagnosis.`,
26005
+ hint: `Inspect: az container logs -n ${state.aciName} -g ${state.resourceGroup}. Reap anyway with --force.`
26006
+ });
26007
+ }
26008
+ const aci = await getAciState({ aciName: state.aciName, resourceGroup: state.resourceGroup, subscriptionId: state.subscriptionId }).catch(() => null);
26009
+ const deadHint = aci?.terminated ? `The installer container has terminated (exit ${String(aci.exitCode ?? "?")}) without reaching done \u2014 reap with --force.` : `Wait for 'm8t bootstrap status --watch' to reach done, or reap with --force if the install is stuck.`;
25952
26010
  throw new LocalCliError({
25953
- code: "BOOTSTRAP_REAP_FAILED_INSTALL",
25954
- message: `The install failed at '${doc.error?.phase ?? doc.phase}'. Leaving the installer up for diagnosis.`,
25955
- hint: `Inspect: az container logs -n ${state.aciName} -g ${state.resourceGroup}. Reap anyway with --force.`
26011
+ code: "BOOTSTRAP_REAP_NOT_DONE",
26012
+ message: `The install is not done yet (status: ${doc.status}, phase: ${doc.phase}).`,
26013
+ hint: deadHint
25956
26014
  });
25957
26015
  }
25958
- const aci = await getAciState({ aciName: state.aciName, resourceGroup: state.resourceGroup, subscriptionId: state.subscriptionId }).catch(() => null);
25959
- const deadHint = aci?.terminated ? `The installer container has terminated (exit ${String(aci.exitCode ?? "?")}) without reaching done \u2014 reap with --force.` : `Wait for 'm8t bootstrap status --watch' to reach done, or reap with --force if the install is stuck.`;
25960
- throw new LocalCliError({
25961
- code: "BOOTSTRAP_REAP_NOT_DONE",
25962
- message: `The install is not done yet (status: ${doc.status}, phase: ${doc.phase}).`,
25963
- hint: deadHint
25964
- });
25965
26016
  }
25966
26017
  await reapInstaller({
25967
26018
  subscriptionId: state.subscriptionId,