@m8t-stack/cli 0.2.69 → 0.2.70

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/dist/cli.js CHANGED
@@ -1364,7 +1364,7 @@ var init_enable_hosted_brain = __esm({
1364
1364
  import { Builtins, Cli } from "clipanion";
1365
1365
 
1366
1366
  // src/lib/package-version.ts
1367
- var CLI_VERSION = "0.2.69";
1367
+ var CLI_VERSION = "0.2.70";
1368
1368
 
1369
1369
  // src/lib/render-error.ts
1370
1370
  init_errors();
@@ -3698,12 +3698,12 @@ function encodeURIPath(str4) {
3698
3698
  return str4.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
3699
3699
  }
3700
3700
  var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
3701
- var createPathTagFunction = (pathEncoder = encodeURIPath) => function path42(statics, ...params) {
3701
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path43(statics, ...params) {
3702
3702
  if (statics.length === 1)
3703
3703
  return statics[0];
3704
3704
  let postPath = false;
3705
3705
  const invalidSegments = [];
3706
- const path43 = statics.reduce((previousValue, currentValue, index) => {
3706
+ const path44 = statics.reduce((previousValue, currentValue, index) => {
3707
3707
  if (/[?#]/.test(currentValue)) {
3708
3708
  postPath = true;
3709
3709
  }
@@ -3720,7 +3720,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path42(sta
3720
3720
  }
3721
3721
  return previousValue + currentValue + (index === params.length ? "" : encoded);
3722
3722
  }, "");
3723
- const pathOnly = path43.split(/[?#]/, 1)[0];
3723
+ const pathOnly = path44.split(/[?#]/, 1)[0];
3724
3724
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
3725
3725
  let match;
3726
3726
  while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -3741,10 +3741,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path42(sta
3741
3741
  }, "");
3742
3742
  throw new OpenAIError(`Path parameters result in path with invalid segments:
3743
3743
  ${invalidSegments.map((e) => e.error).join("\n")}
3744
- ${path43}
3744
+ ${path44}
3745
3745
  ${underline}`);
3746
3746
  }
3747
- return path43;
3747
+ return path44;
3748
3748
  };
3749
3749
  var path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
3750
3750
 
@@ -12012,9 +12012,9 @@ var OpenAI = class {
12012
12012
  this.apiKey = token;
12013
12013
  return true;
12014
12014
  }
12015
- buildURL(path42, query, defaultBaseURL) {
12015
+ buildURL(path43, query, defaultBaseURL) {
12016
12016
  const baseURL = !__classPrivateFieldGet(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
12017
- const url = isAbsoluteURL(path42) ? new URL(path42) : new URL(baseURL + (baseURL.endsWith("/") && path42.startsWith("/") ? path42.slice(1) : path42));
12017
+ const url = isAbsoluteURL(path43) ? new URL(path43) : new URL(baseURL + (baseURL.endsWith("/") && path43.startsWith("/") ? path43.slice(1) : path43));
12018
12018
  const defaultQuery = this.defaultQuery();
12019
12019
  const pathQuery = Object.fromEntries(url.searchParams);
12020
12020
  if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
@@ -12044,24 +12044,24 @@ var OpenAI = class {
12044
12044
  */
12045
12045
  async prepareRequest(request, { url, options }) {
12046
12046
  }
12047
- get(path42, opts) {
12048
- return this.methodRequest("get", path42, opts);
12047
+ get(path43, opts) {
12048
+ return this.methodRequest("get", path43, opts);
12049
12049
  }
12050
- post(path42, opts) {
12051
- return this.methodRequest("post", path42, opts);
12050
+ post(path43, opts) {
12051
+ return this.methodRequest("post", path43, opts);
12052
12052
  }
12053
- patch(path42, opts) {
12054
- return this.methodRequest("patch", path42, opts);
12053
+ patch(path43, opts) {
12054
+ return this.methodRequest("patch", path43, opts);
12055
12055
  }
12056
- put(path42, opts) {
12057
- return this.methodRequest("put", path42, opts);
12056
+ put(path43, opts) {
12057
+ return this.methodRequest("put", path43, opts);
12058
12058
  }
12059
- delete(path42, opts) {
12060
- return this.methodRequest("delete", path42, opts);
12059
+ delete(path43, opts) {
12060
+ return this.methodRequest("delete", path43, opts);
12061
12061
  }
12062
- methodRequest(method, path42, opts) {
12062
+ methodRequest(method, path43, opts) {
12063
12063
  return this.request(Promise.resolve(opts).then((opts2) => {
12064
- return { method, path: path42, ...opts2 };
12064
+ return { method, path: path43, ...opts2 };
12065
12065
  }));
12066
12066
  }
12067
12067
  request(options, remainingRetries = null) {
@@ -12186,8 +12186,8 @@ var OpenAI = class {
12186
12186
  }));
12187
12187
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
12188
12188
  }
12189
- getAPIList(path42, Page2, opts) {
12190
- return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path42, ...opts2 })) : { method: "get", path: path42, ...opts });
12189
+ getAPIList(path43, Page2, opts) {
12190
+ return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path43, ...opts2 })) : { method: "get", path: path43, ...opts });
12191
12191
  }
12192
12192
  requestAPIList(Page2, options) {
12193
12193
  const request = this.makeRequest(options, null, void 0);
@@ -12281,8 +12281,8 @@ var OpenAI = class {
12281
12281
  }
12282
12282
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
12283
12283
  const options = { ...inputOptions };
12284
- const { method, path: path42, query, defaultBaseURL } = options;
12285
- const url = this.buildURL(path42, query, defaultBaseURL);
12284
+ const { method, path: path43, query, defaultBaseURL } = options;
12285
+ const url = this.buildURL(path43, query, defaultBaseURL);
12286
12286
  if ("timeout" in options)
12287
12287
  validatePositiveInteger("timeout", options.timeout);
12288
12288
  options.timeout = options.timeout ?? this.timeout;
@@ -12510,6 +12510,9 @@ function classifyFoundryError(err) {
12510
12510
  }
12511
12511
 
12512
12512
  // src/lib/render-error.ts
12513
+ function renderHint(hint) {
12514
+ return hint.split("\n").join("\n ");
12515
+ }
12513
12516
  function renderError(err, opts) {
12514
12517
  const mode = resolveOutputMode(opts.output, opts.stderr);
12515
12518
  if (err instanceof Error && (err.name === "ExitPromptError" || err.message === "User force closed the prompt")) {
@@ -12533,7 +12536,7 @@ function renderError(err, opts) {
12533
12536
  opts.stderr.write(`${colors.error("error:")} ${err.envelope.message}
12534
12537
  `);
12535
12538
  const hint = resolveBackendHint(err.envelope);
12536
- if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${hint}
12539
+ if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${renderHint(hint)}
12537
12540
  `);
12538
12541
  if (opts.verbose) {
12539
12542
  opts.stderr.write("\n" + colors.dim(renderJson(err.envelope)) + "\n");
@@ -12560,7 +12563,7 @@ function renderError(err, opts) {
12560
12563
  opts.stderr.write(`${colors.error("error:")} ${err.message}
12561
12564
  `);
12562
12565
  const hint = err.hint ?? resolveLocalHint(err.code);
12563
- if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${hint}
12566
+ if (hint) opts.stderr.write(` ${colors.hint("hint:")} ${renderHint(hint)}
12564
12567
  `);
12565
12568
  if (opts.verbose && err.cause instanceof Error) {
12566
12569
  opts.stderr.write("\n" + colors.dim(`caused by: ${err.cause.stack ?? err.cause.message}`) + "\n");
@@ -13325,10 +13328,10 @@ var BindListCommand = class extends M8tCommand {
13325
13328
  const qs = new URLSearchParams();
13326
13329
  if (this.channel) qs.set("channel", this.channel);
13327
13330
  if (this.status) qs.set("status", this.status);
13328
- const path42 = qs.toString().length > 0 ? `/api/bindings?${qs.toString()}` : "/api/bindings";
13331
+ const path43 = qs.toString().length > 0 ? `/api/bindings?${qs.toString()}` : "/api/bindings";
13329
13332
  const data = await apiCall(
13330
13333
  { gatewayUrl: ctx.gatewayUrl, gatewayClientId: ctx.gatewayClientId },
13331
- { method: "GET", path: path42 },
13334
+ { method: "GET", path: path43 },
13332
13335
  (msg) => this.context.stderr.write(msg + "\n")
13333
13336
  );
13334
13337
  if (mode === "json") {
@@ -14159,7 +14162,7 @@ var TeamShowCommand = class extends M8tCommand {
14159
14162
  // src/commands/brain/app-create.ts
14160
14163
  import * as fs4 from "fs";
14161
14164
  import * as os from "os";
14162
- import * as path4 from "path";
14165
+ import * as path5 from "path";
14163
14166
  import { randomBytes } from "crypto";
14164
14167
  import * as readline from "readline/promises";
14165
14168
  import { Command as Command16, Option as Option15 } from "clipanion";
@@ -14359,6 +14362,41 @@ async function findValidBrainApp(credsPath, org, deps = {}) {
14359
14362
  }
14360
14363
  }
14361
14364
 
14365
+ // src/lib/github-app-paths.ts
14366
+ import * as path4 from "path";
14367
+ function brainAppPointerPath(home) {
14368
+ return path4.join(home, ".m8t", "github-app.json");
14369
+ }
14370
+ function orgFileSegment(org) {
14371
+ return org.replace(/[^A-Za-z0-9-]+/g, "-");
14372
+ }
14373
+ function brainAppFilePaths(home, org, appId) {
14374
+ const dir = path4.join(home, ".m8t");
14375
+ const stem = `github-app-${orgFileSegment(org)}-${appId}`;
14376
+ return {
14377
+ pemPath: path4.join(dir, `${stem}.pem`),
14378
+ sidecarPath: path4.join(dir, `${stem}.json`)
14379
+ };
14380
+ }
14381
+ function isPreservable(v) {
14382
+ if (typeof v !== "object" || v === null) return false;
14383
+ const c = v;
14384
+ return typeof c.org === "string" && c.org !== "" && typeof c.appId === "string" && c.appId !== "";
14385
+ }
14386
+ function outgoingSidecarToPreserve(home, pointerText, sidecarExists) {
14387
+ if (pointerText === null) return null;
14388
+ let parsed;
14389
+ try {
14390
+ parsed = JSON.parse(pointerText);
14391
+ } catch {
14392
+ return null;
14393
+ }
14394
+ if (!isPreservable(parsed)) return null;
14395
+ const { sidecarPath } = brainAppFilePaths(home, parsed.org, parsed.appId);
14396
+ if (sidecarExists(sidecarPath)) return null;
14397
+ return { path: sidecarPath, org: parsed.org, appId: parsed.appId };
14398
+ }
14399
+
14362
14400
  // src/lib/gh-helpers.ts
14363
14401
  init_errors();
14364
14402
  import { spawn as spawn2 } from "child_process";
@@ -14539,8 +14577,8 @@ ${r.stderr}`;
14539
14577
  message: `gh api /repos/${slug} failed (exit ${r.exitCode.toString()}): ${(r.stderr || r.stdout).slice(0, 200)}`
14540
14578
  });
14541
14579
  },
14542
- getFile: async (path42) => {
14543
- const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path42}`]);
14580
+ getFile: async (path43) => {
14581
+ const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path43}`]);
14544
14582
  return r.exitCode === 0 ? r.stdout : null;
14545
14583
  },
14546
14584
  isEmpty: async () => {
@@ -14607,6 +14645,36 @@ var BrainAppCreateCommand = class extends M8tCommand {
14607
14645
  forceNew = Option15.Boolean("--new", false, {
14608
14646
  description: "Create a new brain App even if one is already installed on the org."
14609
14647
  });
14648
+ /**
14649
+ * Copy the currently-active App's record to its own per-App file when it has
14650
+ * none. Best-effort: a pointer that cannot be read or written is not a reason
14651
+ * to refuse to create an App, and the outcome is announced either way rather
14652
+ * than swallowed — losing this record silently is the failure being prevented.
14653
+ */
14654
+ preserveOutgoingRecord(credsOut) {
14655
+ let pointerText;
14656
+ try {
14657
+ pointerText = fs4.readFileSync(credsOut, "utf8");
14658
+ } catch {
14659
+ return;
14660
+ }
14661
+ const outgoing = outgoingSidecarToPreserve(os.homedir(), pointerText, fs4.existsSync);
14662
+ if (!outgoing) return;
14663
+ try {
14664
+ fs4.mkdirSync(path5.dirname(outgoing.path), { recursive: true });
14665
+ fs4.writeFileSync(outgoing.path, pointerText, { mode: 384 });
14666
+ this.context.stderr.write(
14667
+ ` ${colors.dim(`kept the current App's record (${outgoing.org}, id ${outgoing.appId}) at ${outgoing.path}`)}
14668
+ `
14669
+ );
14670
+ } catch (e) {
14671
+ this.context.stderr.write(
14672
+ ` ${colors.warn(`could not save the current App's record to ${outgoing.path}: ${e.message}`)}
14673
+ ${colors.warn(`back up ${credsOut} yourself if you need to switch back to that App.`)}
14674
+ `
14675
+ );
14676
+ }
14677
+ }
14610
14678
  async executeCommand() {
14611
14679
  if (!this.org) {
14612
14680
  throw new LocalCliError({
@@ -14616,11 +14684,12 @@ var BrainAppCreateCommand = class extends M8tCommand {
14616
14684
  });
14617
14685
  }
14618
14686
  const org = this.org;
14619
- const pemOut = typeof this.pemOut === "string" ? this.pemOut : path4.join(os.homedir(), ".m8t", "github-app.pem");
14620
- const credsOut = typeof this.credsOut === "string" ? this.credsOut : path4.join(os.homedir(), ".m8t", "github-app.json");
14687
+ const pemOutOverride = typeof this.pemOut === "string" ? this.pemOut : void 0;
14688
+ const credsOut = typeof this.credsOut === "string" ? this.credsOut : brainAppPointerPath(os.homedir());
14621
14689
  const port = Number(this.port);
14622
14690
  const onProgress = (m) => this.context.stderr.write(` ${colors.dim(m)}
14623
14691
  `);
14692
+ this.preserveOutgoingRecord(credsOut);
14624
14693
  const existing = await findValidBrainApp(credsOut, org);
14625
14694
  if (existing) {
14626
14695
  const isTTY = this.context.stdout.isTTY === true;
@@ -14669,7 +14738,9 @@ var BrainAppCreateCommand = class extends M8tCommand {
14669
14738
  }),
14670
14739
  onProgress
14671
14740
  });
14672
- fs4.mkdirSync(path4.dirname(pemOut), { recursive: true });
14741
+ const layout = brainAppFilePaths(os.homedir(), org, app.id);
14742
+ const pemOut = pemOutOverride ?? layout.pemPath;
14743
+ fs4.mkdirSync(path5.dirname(pemOut), { recursive: true });
14673
14744
  fs4.writeFileSync(pemOut, app.pem, { mode: 384 });
14674
14745
  this.context.stdout.write(
14675
14746
  `${colors.success("\u2713")} App created: ${colors.field(app.slug)} (id ${app.id}); pem \u2192 ${pemOut}
@@ -14683,11 +14754,16 @@ ${colors.success("\u2713")} installed on ${org} (installation ${installationId})
14683
14754
  installationId,
14684
14755
  pemPath: pemOut
14685
14756
  };
14686
- fs4.mkdirSync(path4.dirname(credsOut), { recursive: true });
14687
- fs4.writeFileSync(credsOut, JSON.stringify(creds, null, 2), { mode: 384 });
14757
+ const credsJson = JSON.stringify(creds, null, 2);
14758
+ if (!pemOutOverride) {
14759
+ fs4.writeFileSync(layout.sidecarPath, credsJson, { mode: 384 });
14760
+ }
14761
+ fs4.mkdirSync(path5.dirname(credsOut), { recursive: true });
14762
+ fs4.writeFileSync(credsOut, credsJson, { mode: 384 });
14688
14763
  this.context.stdout.write(
14689
- `${colors.success("\u2713")} creds \u2192 ${credsOut}
14690
- `
14764
+ `${colors.success("\u2713")} creds \u2192 ${credsOut} ${colors.dim("(this App is now the active one)")}
14765
+ ` + (pemOutOverride ? "" : ` ${colors.dim(`kept alongside the key: ${layout.sidecarPath}`)}
14766
+ `)
14691
14767
  );
14692
14768
  if (this.output === "json") this.context.stdout.write(JSON.stringify(creds) + "\n");
14693
14769
  return 0;
@@ -14703,7 +14779,7 @@ import { DefaultAzureCredential as DefaultAzureCredential3 } from "@azure/identi
14703
14779
  init_errors();
14704
14780
  import * as fs5 from "fs";
14705
14781
  import * as os2 from "os";
14706
- import * as path5 from "path";
14782
+ import * as path6 from "path";
14707
14783
  function discoverKvUri(env, override) {
14708
14784
  if (override) return override;
14709
14785
  const v = env.AZURE_KEYVAULT_URI ?? env.KEYVAULT_URI;
@@ -14715,7 +14791,7 @@ function discoverKvUri(env, override) {
14715
14791
  });
14716
14792
  }
14717
14793
  function tryResolveRepoRoot() {
14718
- const marker = path5.join(os2.homedir(), ".m8t", "repo-root");
14794
+ const marker = path6.join(os2.homedir(), ".m8t", "repo-root");
14719
14795
  if (!fs5.existsSync(marker)) return null;
14720
14796
  const root = fs5.readFileSync(marker, "utf8").trim();
14721
14797
  return root.length > 0 ? root : null;
@@ -14785,10 +14861,10 @@ var BrainCheckAppCommand = class extends M8tCommand {
14785
14861
  init_esm2();
14786
14862
  import { Command as Command18, Option as Option17 } from "clipanion";
14787
14863
  import { execFileSync, spawnSync } from "child_process";
14788
- import { readFileSync as readFileSync6 } from "fs";
14864
+ import { readFileSync as readFileSync7 } from "fs";
14789
14865
  import * as fs11 from "fs";
14790
14866
  import * as os4 from "os";
14791
- import * as path10 from "path";
14867
+ import * as path11 from "path";
14792
14868
  import * as readline2 from "readline/promises";
14793
14869
  import { DefaultAzureCredential as DefaultAzureCredential4 } from "@azure/identity";
14794
14870
  init_errors();
@@ -14808,6 +14884,9 @@ async function listProjectsForAccount(credential2, accountId) {
14808
14884
  function formatProjectCandidate(c) {
14809
14885
  return `${c.projectName} (account=${c.accountName}, ${c.region})`;
14810
14886
  }
14887
+ function resourceGroupOfArmId(id) {
14888
+ return /\/resourceGroups\/([^/]+)/i.exec(id)?.[1].toLowerCase();
14889
+ }
14811
14890
  async function resolveFoundryProject(opts) {
14812
14891
  const candidates = [];
14813
14892
  const accounts = await authedJsonPagedValues({
@@ -14844,29 +14923,37 @@ async function resolveFoundryProject(opts) {
14844
14923
  const match = candidates.find((c) => c.endpoint === opts.agentEndpoint);
14845
14924
  if (match) return match;
14846
14925
  }
14847
- if (candidates.length === 0) {
14926
+ let scoped = candidates;
14927
+ if (opts.resourceGroup) {
14928
+ const want = opts.resourceGroup.toLowerCase();
14929
+ scoped = candidates.filter((c) => resourceGroupOfArmId(c.accountScope) === want);
14930
+ const dropped = candidates.filter((c) => !scoped.includes(c));
14931
+ if (dropped.length > 0) opts.onScopedOut?.(dropped);
14932
+ }
14933
+ const searched = opts.resourceGroup ? `resource group ${opts.resourceGroup} (subscription ${opts.subscriptionId})` : `subscription ${opts.subscriptionId}`;
14934
+ if (scoped.length === 0) {
14848
14935
  throw new LocalCliError({
14849
14936
  code: "FOUNDRY_PROJECT_ZERO",
14850
- message: `No AIServices Foundry project found in subscription ${opts.subscriptionId}.`,
14937
+ message: `No AIServices Foundry project found in ${searched}.`,
14851
14938
  hint: "Create one with 'm8t foundry create --resource-group <rg> --location <region>', switch subscription with 'az account set --subscription <id>', or pass --endpoint."
14852
14939
  });
14853
14940
  }
14854
- if (candidates.length === 1) return candidates[0];
14941
+ if (scoped.length === 1) return scoped[0];
14855
14942
  if (!opts.interactive) {
14856
14943
  throw new LocalCliError({
14857
14944
  code: "FOUNDRY_PROJECT_MULTIPLE",
14858
- message: `Multiple Foundry projects found: ${candidates.map(formatProjectCandidate).join("; ")}.`,
14859
- hint: `Pass --endpoint <url> to choose. Endpoints: ${candidates.map((c) => c.endpoint).join(" | ")}`
14945
+ message: opts.resourceGroup ? `Resource group ${opts.resourceGroup} holds more than one Foundry project: ${scoped.map(formatProjectCandidate).join("; ")}.` : `Multiple Foundry projects found: ${scoped.map(formatProjectCandidate).join("; ")}.`,
14946
+ hint: `Pass --endpoint <url> to choose. Endpoints: ${scoped.map((c) => c.endpoint).join(" | ")}`
14860
14947
  });
14861
14948
  }
14862
14949
  const endpoint = await select2({
14863
- message: `Multiple Foundry projects in subscription ${opts.subscriptionId}. Choose one:`,
14864
- choices: candidates.map((c) => ({
14950
+ message: `Multiple Foundry projects in ${searched}. Choose one:`,
14951
+ choices: scoped.map((c) => ({
14865
14952
  name: formatProjectCandidate(c),
14866
14953
  value: c.endpoint
14867
14954
  }))
14868
14955
  });
14869
- const chosen = candidates.find((c) => c.endpoint === endpoint);
14956
+ const chosen = scoped.find((c) => c.endpoint === endpoint);
14870
14957
  if (!chosen) {
14871
14958
  throw new LocalCliError({ code: "FOUNDRY_PROJECT_SELECTION_FAILED", message: "No project selected." });
14872
14959
  }
@@ -14876,11 +14963,11 @@ async function resolveFoundryProject(opts) {
14876
14963
  // src/lib/agent-yaml.ts
14877
14964
  init_errors();
14878
14965
  import * as fs6 from "fs";
14879
- import * as path6 from "path";
14966
+ import * as path7 from "path";
14880
14967
  import * as os3 from "os";
14881
14968
  import { parse as parseYaml3, stringify as stringifyYaml3 } from "yaml";
14882
14969
  function agentYamlPath(agentName, home = os3.homedir()) {
14883
- return path6.join(home, ".m8t", "foundry", `${agentName}.yaml`);
14970
+ return path7.join(home, ".m8t", "foundry", `${agentName}.yaml`);
14884
14971
  }
14885
14972
  function readAgentYaml(agentName, home) {
14886
14973
  const file = agentYamlPath(agentName, home);
@@ -14890,7 +14977,7 @@ function readAgentYaml(agentName, home) {
14890
14977
  }
14891
14978
  function writeAgentYaml(agentName, data, home) {
14892
14979
  const file = agentYamlPath(agentName, home);
14893
- fs6.mkdirSync(path6.dirname(file), { recursive: true });
14980
+ fs6.mkdirSync(path7.dirname(file), { recursive: true });
14894
14981
  fs6.writeFileSync(file, stringifyYaml3(data), { mode: 384 });
14895
14982
  }
14896
14983
  function patchAgentYaml(agentName, patch, home) {
@@ -14933,7 +15020,7 @@ function patchAgentYaml(agentName, patch, home) {
14933
15020
  init_esm2();
14934
15021
  init_esm();
14935
15022
  init_errors();
14936
- import * as path7 from "path";
15023
+ import * as path8 from "path";
14937
15024
  import * as fs8 from "fs";
14938
15025
 
14939
15026
  // src/lib/persona-render.ts
@@ -15116,7 +15203,7 @@ async function linkBrain(args) {
15116
15203
  progress(`Token rotated (expires ${rotation.expiresAt.toISOString()})`);
15117
15204
  let foundryVersion;
15118
15205
  if (!alreadyLinked) {
15119
- const loaderPath = path7.join(args.repoRoot, "targets/foundry/brain-loader.md");
15206
+ const loaderPath = path8.join(args.repoRoot, "targets/foundry/brain-loader.md");
15120
15207
  const loaderTemplate = fs8.readFileSync(loaderPath, "utf8");
15121
15208
  const loader = loaderTemplate.replaceAll("{{brain_repo}}", args.repo);
15122
15209
  const yaml = readAgentYaml(args.agentName, args.home);
@@ -15124,7 +15211,7 @@ async function linkBrain(args) {
15124
15211
  let base;
15125
15212
  if (personaPath) {
15126
15213
  progress("Re-rendering persona body with brain loader\u2026");
15127
- const resolved = personaPath.startsWith("/") ? personaPath : path7.join(args.repoRoot, personaPath);
15214
+ const resolved = personaPath.startsWith("/") ? personaPath : path8.join(args.repoRoot, personaPath);
15128
15215
  base = renderPersonaBody(resolved, yaml?.fillableFieldValues ?? {}, args.agentName);
15129
15216
  } else {
15130
15217
  progress("No local persona yaml \u2014 basing instructions on the deployed agent\u2026");
@@ -15281,11 +15368,11 @@ async function createBrainEnabledVersion(args) {
15281
15368
  // src/lib/brain-seed.ts
15282
15369
  init_errors();
15283
15370
  import * as fs10 from "fs";
15284
- import * as path9 from "path";
15371
+ import * as path10 from "path";
15285
15372
 
15286
15373
  // src/lib/seed-manifest.ts
15287
15374
  import * as fs9 from "fs";
15288
- import * as path8 from "path";
15375
+ import * as path9 from "path";
15289
15376
  var SEED_MANIFEST_PATH = ".m8t/seed-manifest.json";
15290
15377
  var SEED_PATHS = ["skills", "references", "targets"];
15291
15378
  function isLineage(v) {
@@ -15318,7 +15405,7 @@ function serializeSeedManifest(m) {
15318
15405
  return JSON.stringify(m, null, 2) + "\n";
15319
15406
  }
15320
15407
  function walkFiles(root, rel = "") {
15321
- const abs = path8.join(root, rel);
15408
+ const abs = path9.join(root, rel);
15322
15409
  if (!fs9.existsSync(abs)) return [];
15323
15410
  const out = [];
15324
15411
  for (const entry of fs9.readdirSync(abs, { withFileTypes: true })) {
@@ -15331,14 +15418,14 @@ function walkFiles(root, rel = "") {
15331
15418
  function deriveOwnedPaths(seedDir) {
15332
15419
  const owned = /* @__PURE__ */ new Set([SEED_MANIFEST_PATH]);
15333
15420
  for (const sub of SEED_PATHS) {
15334
- for (const rel of walkFiles(path8.join(seedDir, sub))) owned.add(`${sub}/${rel}`);
15421
+ for (const rel of walkFiles(path9.join(seedDir, sub))) owned.add(`${sub}/${rel}`);
15335
15422
  }
15336
15423
  return [...owned].sort((a, b) => a.localeCompare(b));
15337
15424
  }
15338
15425
 
15339
15426
  // src/lib/brain-seed.ts
15340
15427
  function resolveSeed(name) {
15341
- const dir = path9.join(resolveRepoRoot(), "brain-seeds", name);
15428
+ const dir = path10.join(resolveRepoRoot(), "brain-seeds", name);
15342
15429
  if (!fs10.existsSync(dir)) {
15343
15430
  throw new LocalCliError({
15344
15431
  code: "SEED_NOT_FOUND",
@@ -15361,8 +15448,8 @@ function writeSeedMarker(args) {
15361
15448
  refreshedToVersion: args.version,
15362
15449
  ownedPaths: deriveOwnedPaths(args.seedDir)
15363
15450
  }]);
15364
- const dest = path9.join(args.destDir, SEED_MANIFEST_PATH);
15365
- fs10.mkdirSync(path9.dirname(dest), { recursive: true });
15451
+ const dest = path10.join(args.destDir, SEED_MANIFEST_PATH);
15452
+ fs10.mkdirSync(path10.dirname(dest), { recursive: true });
15366
15453
  fs10.writeFileSync(dest, serializeSeedManifest(manifest));
15367
15454
  }
15368
15455
 
@@ -15607,7 +15694,7 @@ function appRepoProbe(args) {
15607
15694
  const res = await doFetch(`${GH_API}/repos/${args.repo}`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
15608
15695
  return res.status;
15609
15696
  },
15610
- getFile: (path42) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path42, fetchImpl: args.fetchImpl }),
15697
+ getFile: (path43) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path43, fetchImpl: args.fetchImpl }),
15611
15698
  isEmpty: async () => {
15612
15699
  const res = await doFetch(`${GH_API}/repos/${args.repo}/contents`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
15613
15700
  return res.status === 404;
@@ -15904,7 +15991,7 @@ var BrainCreateCommand = class extends M8tCommand {
15904
15991
  if (useAppPath) {
15905
15992
  await assertInstallationPermissions({
15906
15993
  appId: appIdOpt,
15907
- privateKeyPem: readFileSync6(appPemOpt, "utf8"),
15994
+ privateKeyPem: readFileSync7(appPemOpt, "utf8"),
15908
15995
  installationId: installationIdOpt,
15909
15996
  org: owner,
15910
15997
  onUnverified: (m) => this.context.stderr.write(` ${colors.dim(`warning: ${m}`)}
@@ -15936,7 +16023,7 @@ var BrainCreateCommand = class extends M8tCommand {
15936
16023
  agentEndpoint
15937
16024
  });
15938
16025
  const repoRoot = resolveRepoRoot();
15939
- const templateSrc = path10.join(repoRoot, "brain-template");
16026
+ const templateSrc = path11.join(repoRoot, "brain-template");
15940
16027
  if (!fs11.existsSync(templateSrc)) {
15941
16028
  throw new LocalCliError({
15942
16029
  code: "TEMPLATE_MISSING",
@@ -15944,7 +16031,7 @@ var BrainCreateCommand = class extends M8tCommand {
15944
16031
  hint: "Ensure brain-template/ exists at the repo root (same level as apps/)."
15945
16032
  });
15946
16033
  }
15947
- const tmpDir = fs11.mkdtempSync(path10.join(os4.tmpdir(), `m8t-brain-create-${worker}-`));
16034
+ const tmpDir = fs11.mkdtempSync(path11.join(os4.tmpdir(), `m8t-brain-create-${worker}-`));
15948
16035
  let result2;
15949
16036
  let resolvedInstallationId = null;
15950
16037
  const force = this.reuse === true ? "reuse" : this.newName === true ? "new" : void 0;
@@ -15954,7 +16041,7 @@ var BrainCreateCommand = class extends M8tCommand {
15954
16041
  if (useAppPath) {
15955
16042
  token = await mintInstallationTokenFromPem({
15956
16043
  appId: appIdOpt,
15957
- privateKeyPem: readFileSync6(appPemOpt, "utf8"),
16044
+ privateKeyPem: readFileSync7(appPemOpt, "utf8"),
15958
16045
  installationId: installationIdOpt
15959
16046
  });
15960
16047
  const tok = token;
@@ -16530,7 +16617,7 @@ init_esm2();
16530
16617
  init_errors();
16531
16618
  import * as fs12 from "fs";
16532
16619
  import * as os5 from "os";
16533
- import * as path11 from "path";
16620
+ import * as path12 from "path";
16534
16621
  init_foundry_agent_get();
16535
16622
  init_foundry_agent_version();
16536
16623
  var FOUNDRY_ARM_API2 = "2025-04-01-preview";
@@ -16561,7 +16648,7 @@ async function unlinkBrain(args) {
16561
16648
  if (yaml?.personaPath) {
16562
16649
  let personaPath = yaml.personaPath;
16563
16650
  if (!personaPath.startsWith("/")) {
16564
- const marker = path11.join(args.home ?? os5.homedir(), ".m8t", "repo-root");
16651
+ const marker = path12.join(args.home ?? os5.homedir(), ".m8t", "repo-root");
16565
16652
  if (!fs12.existsSync(marker)) {
16566
16653
  throw new LocalCliError({
16567
16654
  code: "PERSONA_PATH_NOT_ABSOLUTE",
@@ -16569,7 +16656,7 @@ async function unlinkBrain(args) {
16569
16656
  hint: "Re-run 'm8t install' from a fresh m8t checkout (writes ~/.m8t/repo-root) \u2014 or edit the personaPath to absolute."
16570
16657
  });
16571
16658
  }
16572
- personaPath = path11.join(fs12.readFileSync(marker, "utf8").trim(), personaPath);
16659
+ personaPath = path12.join(fs12.readFileSync(marker, "utf8").trim(), personaPath);
16573
16660
  }
16574
16661
  strippedInstructions = renderPersonaBody(personaPath, yaml.fillableFieldValues ?? {}, args.agentName);
16575
16662
  } else {
@@ -16791,24 +16878,24 @@ init_errors();
16791
16878
 
16792
16879
  // src/lib/deploy-prompt-advisor.ts
16793
16880
  import * as fs13 from "fs";
16794
- import * as path12 from "path";
16881
+ import * as path13 from "path";
16795
16882
  import { parse as parseYaml6 } from "yaml";
16796
16883
  init_foundry_agents();
16797
16884
  init_errors();
16798
16885
  init_esm();
16799
16886
  function findPersonasRoot(hint) {
16800
- let dir = path12.resolve(hint);
16801
- const fsRoot = path12.parse(dir).root;
16887
+ let dir = path13.resolve(hint);
16888
+ const fsRoot = path13.parse(dir).root;
16802
16889
  for (; ; ) {
16803
- if (fs13.existsSync(path12.join(dir, "personas"))) return dir;
16804
- const parent = path12.dirname(dir);
16890
+ if (fs13.existsSync(path13.join(dir, "personas"))) return dir;
16891
+ const parent = path13.dirname(dir);
16805
16892
  if (parent === dir || dir === fsRoot) return null;
16806
16893
  dir = parent;
16807
16894
  }
16808
16895
  }
16809
16896
  async function deployPromptAdvisor(args) {
16810
16897
  const resolvedRoot = findPersonasRoot(args.repoRoot);
16811
- const personaPath = resolvedRoot ? path12.join(resolvedRoot, "personas", args.persona, "persona.md") : path12.join(args.repoRoot, "personas", args.persona, "persona.md");
16898
+ const personaPath = resolvedRoot ? path13.join(resolvedRoot, "personas", args.persona, "persona.md") : path13.join(args.repoRoot, "personas", args.persona, "persona.md");
16812
16899
  let raw;
16813
16900
  try {
16814
16901
  raw = fs13.readFileSync(personaPath, "utf8");
@@ -17572,7 +17659,7 @@ ${colors.success("\u2713")} removed ${colors.field(name)}.
17572
17659
  };
17573
17660
 
17574
17661
  // src/commands/a2a/enable.ts
17575
- import * as path14 from "path";
17662
+ import * as path15 from "path";
17576
17663
  import { Command as Command26, Option as Option25 } from "clipanion";
17577
17664
  import { DefaultAzureCredential as DefaultAzureCredential11 } from "@azure/identity";
17578
17665
  init_errors();
@@ -17581,7 +17668,7 @@ init_errors();
17581
17668
  init_errors();
17582
17669
  import * as fs16 from "fs";
17583
17670
  import * as os6 from "os";
17584
- import * as path13 from "path";
17671
+ import * as path14 from "path";
17585
17672
  import { parse as parseYaml8 } from "yaml";
17586
17673
  var A2A_PATH = "/api/a2a/mcp";
17587
17674
  function resolveBridgeUrl(opts) {
@@ -17603,7 +17690,7 @@ function clean(v) {
17603
17690
  return t.length ? t : void 0;
17604
17691
  }
17605
17692
  function readConfigGatewayUrl(home) {
17606
- const cfg = path13.join(home ?? os6.homedir(), ".m8t", "config.yaml");
17693
+ const cfg = path14.join(home ?? os6.homedir(), ".m8t", "config.yaml");
17607
17694
  if (!fs16.existsSync(cfg)) return void 0;
17608
17695
  try {
17609
17696
  const o = parseYaml8(fs16.readFileSync(cfg, "utf8"));
@@ -17675,11 +17762,11 @@ var A2aEnableCommand = class extends M8tCommand {
17675
17762
  resolvePersonaPath() {
17676
17763
  if (typeof this.persona === "string" && this.persona.length > 0) {
17677
17764
  if (this.persona.includes("/") || this.persona.endsWith(".md")) return this.persona;
17678
- return path14.join(resolveRepoRoot(), "personas", this.persona, "persona.md");
17765
+ return path15.join(resolveRepoRoot(), "personas", this.persona, "persona.md");
17679
17766
  }
17680
17767
  const yaml = readAgentYaml(this.worker);
17681
17768
  if (yaml?.personaPath) {
17682
- return yaml.personaPath.startsWith("/") ? yaml.personaPath : path14.join(resolveRepoRoot(), yaml.personaPath);
17769
+ return yaml.personaPath.startsWith("/") ? yaml.personaPath : path15.join(resolveRepoRoot(), yaml.personaPath);
17683
17770
  }
17684
17771
  throw new LocalCliError({ code: "A2A_NO_PERSONA", message: `Could not resolve a persona for '${this.worker}'. Pass --persona <name>.` });
17685
17772
  }
@@ -17737,7 +17824,7 @@ import { Command as Command28 } from "clipanion";
17737
17824
  import { createHash as createHash2 } from "crypto";
17738
17825
  import * as fs17 from "fs";
17739
17826
  import * as os7 from "os";
17740
- import * as path15 from "path";
17827
+ import * as path16 from "path";
17741
17828
  function readVersionFrontmatter(file) {
17742
17829
  if (!fs17.existsSync(file)) return "";
17743
17830
  const text = fs17.readFileSync(file, "utf8");
@@ -17755,20 +17842,20 @@ var SIDECAR_FILENAME = "m8t-architect.m8t-skill.json";
17755
17842
  var LEGACY_SIDECAR_FILENAME = ".m8t-skill.json";
17756
17843
  function vsCodeUserDataDir() {
17757
17844
  if (process.platform === "darwin") {
17758
- return path15.join(os7.homedir(), "Library", "Application Support", "Code", "User");
17845
+ return path16.join(os7.homedir(), "Library", "Application Support", "Code", "User");
17759
17846
  }
17760
17847
  if (process.platform === "win32") {
17761
- const appData = process.env.APPDATA ?? path15.join(os7.homedir(), "AppData", "Roaming");
17762
- return path15.join(appData, "Code", "User");
17848
+ const appData = process.env.APPDATA ?? path16.join(os7.homedir(), "AppData", "Roaming");
17849
+ return path16.join(appData, "Code", "User");
17763
17850
  }
17764
17851
  return null;
17765
17852
  }
17766
17853
  function vsCodePromptsDir() {
17767
17854
  const userData = vsCodeUserDataDir();
17768
17855
  if (!userData) return null;
17769
- const prompts = path15.join(userData, "prompts");
17856
+ const prompts = path16.join(userData, "prompts");
17770
17857
  if (fs17.existsSync(prompts)) return prompts;
17771
- const promptFiles = path15.join(userData, "prompt-files");
17858
+ const promptFiles = path16.join(userData, "prompt-files");
17772
17859
  if (fs17.existsSync(promptFiles)) return promptFiles;
17773
17860
  return prompts;
17774
17861
  }
@@ -17780,7 +17867,7 @@ var COPILOT_CLI_SKILLS_ROOTS = [
17780
17867
  function sidecarLocations() {
17781
17868
  const home = os7.homedir();
17782
17869
  const locations = [
17783
- { host: "Claude Code", dir: path15.join(home, ".claude", "skills", "m8t-architect") }
17870
+ { host: "Claude Code", dir: path16.join(home, ".claude", "skills", "m8t-architect") }
17784
17871
  ];
17785
17872
  const vsCodeDir = vsCodePromptsDir();
17786
17873
  if (vsCodeDir) {
@@ -17789,7 +17876,7 @@ function sidecarLocations() {
17789
17876
  for (const segments of COPILOT_CLI_SKILLS_ROOTS) {
17790
17877
  locations.push({
17791
17878
  host: "GitHub Copilot CLI",
17792
- dir: path15.join(home, ...segments, "m8t-architect")
17879
+ dir: path16.join(home, ...segments, "m8t-architect")
17793
17880
  });
17794
17881
  }
17795
17882
  return locations;
@@ -17798,7 +17885,7 @@ function resolveSidecar() {
17798
17885
  let best = null;
17799
17886
  for (const loc of sidecarLocations()) {
17800
17887
  for (const filename of [SIDECAR_FILENAME, LEGACY_SIDECAR_FILENAME]) {
17801
- const candidate2 = path15.join(loc.dir, filename);
17888
+ const candidate2 = path16.join(loc.dir, filename);
17802
17889
  let mtimeMs;
17803
17890
  try {
17804
17891
  mtimeMs = fs17.statSync(candidate2).mtimeMs;
@@ -17813,7 +17900,7 @@ function resolveSidecar() {
17813
17900
  return best;
17814
17901
  }
17815
17902
  function checkArchitectDrift() {
17816
- const sourcePath = path15.join(
17903
+ const sourcePath = path16.join(
17817
17904
  resolveRepoRoot(),
17818
17905
  "personas",
17819
17906
  "m8t-architect",
@@ -17896,7 +17983,7 @@ var ArchitectCheckCommand = class extends M8tCommand {
17896
17983
 
17897
17984
  // src/commands/coder/deploy.ts
17898
17985
  init_esm2();
17899
- import * as path17 from "path";
17986
+ import * as path18 from "path";
17900
17987
  import { Command as Command29, Option as Option27 } from "clipanion";
17901
17988
  import { DefaultAzureCredential as DefaultAzureCredential13 } from "@azure/identity";
17902
17989
  init_errors();
@@ -18164,13 +18251,13 @@ async function deployHostedWorker(args) {
18164
18251
 
18165
18252
  // src/lib/persona.ts
18166
18253
  import * as fs18 from "fs";
18167
- import * as path16 from "path";
18254
+ import * as path17 from "path";
18168
18255
  import { parse as parseYaml9 } from "yaml";
18169
18256
  function findRepoRoot(startDir) {
18170
- let dir = path16.resolve(startDir);
18257
+ let dir = path17.resolve(startDir);
18171
18258
  for (; ; ) {
18172
- if (fs18.existsSync(path16.join(dir, "personas"))) return dir;
18173
- const parent = path16.dirname(dir);
18259
+ if (fs18.existsSync(path17.join(dir, "personas"))) return dir;
18260
+ const parent = path17.dirname(dir);
18174
18261
  if (parent === dir) return null;
18175
18262
  dir = parent;
18176
18263
  }
@@ -18178,7 +18265,7 @@ function findRepoRoot(startDir) {
18178
18265
  function resolvePersona(persona, cwd = process.cwd()) {
18179
18266
  const root = findRepoRoot(cwd);
18180
18267
  if (!root) return { persona, personaVersion: null };
18181
- const file = path16.join(root, "personas", persona, "persona.md");
18268
+ const file = path17.join(root, "personas", persona, "persona.md");
18182
18269
  let raw;
18183
18270
  try {
18184
18271
  raw = fs18.readFileSync(file, "utf-8");
@@ -18538,7 +18625,7 @@ var CoderDeployCommand = class extends M8tCommand {
18538
18625
  projectEndpoint: project.endpoint,
18539
18626
  projectArmId: `${project.accountScope}/projects/${project.projectName}`,
18540
18627
  agentName: this.name,
18541
- personaPath: path17.join(resolveRepoRoot(), "personas", personaName, "persona.md"),
18628
+ personaPath: path18.join(resolveRepoRoot(), "personas", personaName, "persona.md"),
18542
18629
  bridgeUrl,
18543
18630
  onProgress
18544
18631
  });
@@ -18665,7 +18752,7 @@ var CoderTeardownCommand = class extends M8tCommand {
18665
18752
 
18666
18753
  // src/commands/azure-exec/deploy.ts
18667
18754
  init_esm2();
18668
- import * as path18 from "path";
18755
+ import * as path19 from "path";
18669
18756
  import { Command as Command31, Option as Option29 } from "clipanion";
18670
18757
  import { DefaultAzureCredential as DefaultAzureCredential15 } from "@azure/identity";
18671
18758
  init_errors();
@@ -18941,7 +19028,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
18941
19028
  kvUri
18942
19029
  });
18943
19030
  onProgress?.("a2a-enabling as a target\u2026");
18944
- const personaPath = path18.join(resolveRepoRoot(), "personas", "azure-executor", "persona.md");
19031
+ const personaPath = path19.join(resolveRepoRoot(), "personas", "azure-executor", "persona.md");
18945
19032
  const bridgeUrl = resolveBridgeUrl({
18946
19033
  flag: typeof this.gatewayUrl === "string" ? this.gatewayUrl : void 0,
18947
19034
  env: processEnv
@@ -19107,8 +19194,8 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
19107
19194
  hint: "Pass a ghcr.io/<owner>/<name> repo, or use the BYOC private-ACR deploy flow."
19108
19195
  });
19109
19196
  }
19110
- const path42 = repo.replace(/^ghcr\.io\//, "");
19111
- const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${path42}:pull`);
19197
+ const path43 = repo.replace(/^ghcr\.io\//, "");
19198
+ const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${path43}:pull`);
19112
19199
  if (!tokenRes.ok) {
19113
19200
  throw new LocalCliError({
19114
19201
  code: "PLATFORM_GHCR_TOKEN_FAILED",
@@ -19124,7 +19211,7 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
19124
19211
  hint: "Make the package public (deploy/ghcr-package-visibility.md), then retry."
19125
19212
  });
19126
19213
  }
19127
- const tagsRes = await fetchImpl(`https://ghcr.io/v2/${path42}/tags/list`, {
19214
+ const tagsRes = await fetchImpl(`https://ghcr.io/v2/${path43}/tags/list`, {
19128
19215
  headers: { Authorization: `Bearer ${token}` }
19129
19216
  });
19130
19217
  if (!tagsRes.ok) {
@@ -19409,7 +19496,7 @@ async function fetchManifest(source, deps = {}) {
19409
19496
  // src/lib/release-content.ts
19410
19497
  import * as fs20 from "fs";
19411
19498
  import * as os8 from "os";
19412
- import * as path19 from "path";
19499
+ import * as path20 from "path";
19413
19500
  import { execFileSync as execFileSync2 } from "child_process";
19414
19501
  init_errors();
19415
19502
  var OWNER_REPO = "m8t-labs/m8t";
@@ -19448,15 +19535,15 @@ function verifyPersonaTrees(manifest, tree) {
19448
19535
  }
19449
19536
  async function resolveReleaseContent(manifest, opts = {}) {
19450
19537
  if (opts.contentDir) {
19451
- if (!fs20.existsSync(path19.join(opts.contentDir, "personas"))) {
19538
+ if (!fs20.existsSync(path20.join(opts.contentDir, "personas"))) {
19452
19539
  throw new LocalCliError({ code: "PLATFORM_CONTENT_DIR_INVALID", message: `--content-dir '${opts.contentDir}' has no personas/ \u2014 not a repo checkout.` });
19453
19540
  }
19454
19541
  return opts.contentDir;
19455
19542
  }
19456
19543
  const commit = manifest.platform.commit;
19457
- const cacheRoot = opts.cacheRoot ?? path19.join(os8.homedir(), ".m8t", "cache");
19458
- const dest = path19.join(cacheRoot, `release-${commit}`);
19459
- if (fs20.existsSync(path19.join(dest, "personas"))) return dest;
19544
+ const cacheRoot = opts.cacheRoot ?? path20.join(os8.homedir(), ".m8t", "cache");
19545
+ const dest = path20.join(cacheRoot, `release-${commit}`);
19546
+ if (fs20.existsSync(path20.join(dest, "personas"))) return dest;
19460
19547
  const fetchImpl = opts.fetchImpl ?? fetch;
19461
19548
  const ghToken = opts.ghToken ?? getGhToken;
19462
19549
  let token;
@@ -19471,18 +19558,18 @@ async function resolveReleaseContent(manifest, opts = {}) {
19471
19558
  throw new LocalCliError({ code: "PLATFORM_TARBALL_FETCH_FAILED", message: `GET ${url} \u2192 HTTP ${res.status.toString()}.` });
19472
19559
  }
19473
19560
  fs20.mkdirSync(cacheRoot, { recursive: true });
19474
- const tmp = fs20.mkdtempSync(path19.join(cacheRoot, `.dl-${commit.slice(0, 8)}-`));
19561
+ const tmp = fs20.mkdtempSync(path20.join(cacheRoot, `.dl-${commit.slice(0, 8)}-`));
19475
19562
  try {
19476
- const tgz = path19.join(tmp, "src.tar.gz");
19563
+ const tgz = path20.join(tmp, "src.tar.gz");
19477
19564
  fs20.writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
19478
- const unpacked = path19.join(tmp, "unpacked");
19565
+ const unpacked = path20.join(tmp, "unpacked");
19479
19566
  fs20.mkdirSync(unpacked);
19480
19567
  extractTarGz(tgz, unpacked);
19481
19568
  try {
19482
19569
  fs20.renameSync(unpacked, dest);
19483
19570
  } catch (e) {
19484
19571
  const err = e;
19485
- const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs20.existsSync(path19.join(dest, "personas"));
19572
+ const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs20.existsSync(path20.join(dest, "personas"));
19486
19573
  if (!isBenignRace) {
19487
19574
  throw new LocalCliError({
19488
19575
  code: "PLATFORM_CACHE_PUBLISH_FAILED",
@@ -19649,13 +19736,13 @@ async function readStamp(opts) {
19649
19736
  // src/lib/platform-converge.ts
19650
19737
  init_esm();
19651
19738
  import * as fs22 from "fs";
19652
- import * as path21 from "path";
19739
+ import * as path22 from "path";
19653
19740
  import { parse as parseYaml10 } from "yaml";
19654
19741
 
19655
19742
  // src/lib/deploy.ts
19656
19743
  import * as fs21 from "fs/promises";
19657
19744
  import * as os9 from "os";
19658
- import * as path20 from "path";
19745
+ import * as path21 from "path";
19659
19746
  init_errors();
19660
19747
  var FOUNDRY_TRACING_MODES = ["project", "account", "skip"];
19661
19748
  function parseFoundryTracingMode(v) {
@@ -19714,7 +19801,7 @@ function buildBicepParams(p) {
19714
19801
  return params;
19715
19802
  }
19716
19803
  async function resolveRepoRoot2(home = os9.homedir()) {
19717
- const marker = path20.join(home, ".m8t", "repo-root");
19804
+ const marker = path21.join(home, ".m8t", "repo-root");
19718
19805
  try {
19719
19806
  const root = (await fs21.readFile(marker, "utf8")).trim();
19720
19807
  if (!root) throw new Error("empty");
@@ -19802,7 +19889,7 @@ function buildDeployResult(args) {
19802
19889
  };
19803
19890
  }
19804
19891
  async function runBicepDeployment(opts) {
19805
- const bicepPath = path20.join(opts.repoRoot, "deploy", "main.bicep");
19892
+ const bicepPath = path21.join(opts.repoRoot, "deploy", "main.bicep");
19806
19893
  const result2 = JSON.parse(
19807
19894
  await runAz([
19808
19895
  "deployment",
@@ -20212,7 +20299,7 @@ function brainRepoOf(current) {
20212
20299
  }
20213
20300
  async function applyPersona(a, ctx, opts) {
20214
20301
  const current = await getAgentVersion({ credential: ctx.credential, projectEndpoint: opts.project.endpoint, agentName: opts.agentName });
20215
- const personaPath = path21.join(opts.personaDir, "persona.md");
20302
+ const personaPath = path22.join(opts.personaDir, "persona.md");
20216
20303
  const yamlValues = readAgentYaml(opts.agentName)?.fillableFieldValues ?? null;
20217
20304
  const values = resolveFillableValues(current, yamlValues);
20218
20305
  const declared = declaredFillableFields(personaPath);
@@ -20317,6 +20404,33 @@ function renderLiveVerify(v, apiVersion, fmt2 = { ok: (s) => s, warn: (s) => s }
20317
20404
  ];
20318
20405
  }
20319
20406
 
20407
+ // src/lib/gateway-api.ts
20408
+ function versionFromEnvelope(body) {
20409
+ if (typeof body !== "object" || body === null) return void 0;
20410
+ const data = body.data;
20411
+ if (typeof data !== "object" || data === null) return void 0;
20412
+ const version = data.version;
20413
+ return typeof version === "string" && version.length > 0 ? version : void 0;
20414
+ }
20415
+ function renderVersionRead(read) {
20416
+ if (read.kind === "version") return read.version;
20417
+ if (read.kind === "auth-gated") return "unknown (auth-gated)";
20418
+ return "unknown";
20419
+ }
20420
+ async function readGatewayVersion(gatewayUrl, fetchImpl = fetch) {
20421
+ let res;
20422
+ try {
20423
+ res = await fetchImpl(`${gatewayUrl}/api/version`, { method: "GET" });
20424
+ } catch (e) {
20425
+ return { kind: "unreachable", detail: e.message };
20426
+ }
20427
+ if (res.status === 401 || res.status === 403) return { kind: "auth-gated", status: res.status };
20428
+ if (!res.ok) return { kind: "http-error", status: res.status };
20429
+ const body = await res.json().catch(() => void 0);
20430
+ const version = versionFromEnvelope(body);
20431
+ return version === void 0 ? { kind: "no-version" } : { kind: "version", version };
20432
+ }
20433
+
20320
20434
  // src/commands/platform/status.ts
20321
20435
  var PlatformStatusCommand = class extends M8tCommand {
20322
20436
  static paths = [["platform", "status"]];
@@ -20440,18 +20554,7 @@ var PlatformStatusCommand = class extends M8tCommand {
20440
20554
  } catch {
20441
20555
  liveImage = void 0;
20442
20556
  }
20443
- let apiVersion = "unknown";
20444
- try {
20445
- const res = await fetch(`${gatewayUrl}/api/version`, { method: "GET" });
20446
- if (res.ok) {
20447
- const body = await res.json().catch(() => ({}));
20448
- apiVersion = body.version ?? "unknown";
20449
- } else if (res.status === 401 || res.status === 403) {
20450
- apiVersion = "unknown (auth-gated)";
20451
- }
20452
- } catch {
20453
- apiVersion = "unknown";
20454
- }
20557
+ const apiVersion = renderVersionRead(await readGatewayVersion(gatewayUrl));
20455
20558
  return {
20456
20559
  gateway: compareGatewayBinding({
20457
20560
  stampTag: stampGatewayTag ?? "unknown",
@@ -20472,7 +20575,7 @@ import { confirm as confirm5 } from "@inquirer/prompts";
20472
20575
  import { DefaultAzureCredential as DefaultAzureCredential17 } from "@azure/identity";
20473
20576
 
20474
20577
  // src/lib/platform-converge-cli.ts
20475
- import * as path25 from "path";
20578
+ import * as path26 from "path";
20476
20579
 
20477
20580
  // src/lib/platform-infra-params.ts
20478
20581
  import { TableClient as TableClient3 } from "@azure/data-tables";
@@ -20557,17 +20660,17 @@ init_errors();
20557
20660
 
20558
20661
  // src/lib/seed-refresh-driver.ts
20559
20662
  init_esm2();
20560
- import * as path24 from "path";
20663
+ import * as path25 from "path";
20561
20664
 
20562
20665
  // src/lib/seed-refresh.ts
20563
20666
  init_errors();
20564
20667
  import * as fs24 from "fs";
20565
- import * as path23 from "path";
20668
+ import * as path24 from "path";
20566
20669
 
20567
20670
  // src/lib/seed-merge.ts
20568
20671
  import * as fs23 from "fs";
20569
20672
  import * as os10 from "os";
20570
- import * as path22 from "path";
20673
+ import * as path23 from "path";
20571
20674
  import { spawnSync as spawnSync3 } from "child_process";
20572
20675
  function isProbablyText(s) {
20573
20676
  return !s.includes("\0");
@@ -20577,11 +20680,11 @@ function mergeThreeWay(ours, base, theirs) {
20577
20680
  return { ok: false, merged: "" };
20578
20681
  }
20579
20682
  const lf = (s) => s.replace(/\r\n/g, "\n");
20580
- const dir = fs23.mkdtempSync(path22.join(os10.tmpdir(), "seed-merge-"));
20683
+ const dir = fs23.mkdtempSync(path23.join(os10.tmpdir(), "seed-merge-"));
20581
20684
  try {
20582
- const o = path22.join(dir, "ours");
20583
- const b = path22.join(dir, "base");
20584
- const t = path22.join(dir, "theirs");
20685
+ const o = path23.join(dir, "ours");
20686
+ const b = path23.join(dir, "base");
20687
+ const t = path23.join(dir, "theirs");
20585
20688
  fs23.writeFileSync(o, lf(ours));
20586
20689
  fs23.writeFileSync(b, lf(base));
20587
20690
  fs23.writeFileSync(t, lf(theirs));
@@ -20601,25 +20704,25 @@ function mergeThreeWay(ours, base, theirs) {
20601
20704
  fs23.rmSync(dir, { recursive: true, force: true });
20602
20705
  }
20603
20706
  }
20604
- var skip = (path42, skipReason) => ({ path: path42, kind: "skip", skipReason });
20707
+ var skip = (path43, skipReason) => ({ path: path43, kind: "skip", skipReason });
20605
20708
  function classifyCandidate(c) {
20606
- const { path: path42, base, ours, theirs } = c;
20607
- if (theirs === base) return { path: path42, kind: "noop" };
20709
+ const { path: path43, base, ours, theirs } = c;
20710
+ if (theirs === base) return { path: path43, kind: "noop" };
20608
20711
  if (base === null) {
20609
- if (theirs === null) return { path: path42, kind: "noop" };
20610
- if (ours === null) return { path: path42, kind: "add", content: theirs };
20611
- if (ours === theirs) return { path: path42, kind: "noop" };
20612
- return skip(path42, "you already have a file at this path");
20712
+ if (theirs === null) return { path: path43, kind: "noop" };
20713
+ if (ours === null) return { path: path43, kind: "add", content: theirs };
20714
+ if (ours === theirs) return { path: path43, kind: "noop" };
20715
+ return skip(path43, "you already have a file at this path");
20613
20716
  }
20614
20717
  if (ours === null) {
20615
- return theirs === null ? { path: path42, kind: "noop" } : skip(path42, "you removed this file; upstream changed it");
20718
+ return theirs === null ? { path: path43, kind: "noop" } : skip(path43, "you removed this file; upstream changed it");
20616
20719
  }
20617
20720
  if (theirs === null) {
20618
- return ours === base ? { path: path42, kind: "delete" } : skip(path42, "you edited this file; upstream removed it");
20721
+ return ours === base ? { path: path43, kind: "delete" } : skip(path43, "you edited this file; upstream removed it");
20619
20722
  }
20620
- if (ours === base) return { path: path42, kind: "update", content: theirs };
20723
+ if (ours === base) return { path: path43, kind: "update", content: theirs };
20621
20724
  const m = mergeThreeWay(ours, base, theirs);
20622
- return m.ok ? { path: path42, kind: "update", content: m.merged } : skip(path42, "your edits conflict with the update");
20725
+ return m.ok ? { path: path43, kind: "update", content: m.merged } : skip(path43, "your edits conflict with the update");
20623
20726
  }
20624
20727
 
20625
20728
  // src/lib/seed-pr-body.ts
@@ -20654,7 +20757,7 @@ function composeSeedPrBody(s) {
20654
20757
  // src/lib/seed-refresh.ts
20655
20758
  function readIf(dir, rel) {
20656
20759
  if (!dir) return null;
20657
- const abs = path23.join(dir, rel);
20760
+ const abs = path24.join(dir, rel);
20658
20761
  return fs24.existsSync(abs) ? fs24.readFileSync(abs, "utf8") : null;
20659
20762
  }
20660
20763
  async function assembleCandidates(args) {
@@ -20787,7 +20890,7 @@ function dedupeBrainRepos(agents) {
20787
20890
  function seedContentDir(contentRoot, manifest, seedName) {
20788
20891
  const items = manifest.components.brainSeeds.items;
20789
20892
  if (!Object.hasOwn(items, seedName)) return null;
20790
- return path24.join(contentRoot, items[seedName].path);
20893
+ return path25.join(contentRoot, items[seedName].path);
20791
20894
  }
20792
20895
  function bindRepoApi(token, repo) {
20793
20896
  return {
@@ -20804,7 +20907,7 @@ function bindRepoApi(token, repo) {
20804
20907
  openPr: (head, base, title, body) => openPullRequestViaApp({ token, repo, base, head, title, body }),
20805
20908
  updatePr: (n, title, body) => updatePullRequestViaApp({ token, repo, number: n, title, body }),
20806
20909
  closePr: (n, comment) => closePullRequestViaApp({ token, repo, number: n, comment }),
20807
- readFileAtRef: (path42, ref) => readRepoFileViaApp({ token, repo, path: path42, ref })
20910
+ readFileAtRef: (path43, ref) => readRepoFileViaApp({ token, repo, path: path43, ref })
20808
20911
  };
20809
20912
  }
20810
20913
  async function runSeedRefresh(args) {
@@ -20917,7 +21020,7 @@ async function buildConvergeDeps(args) {
20917
21020
  const persona = a.metadata.persona;
20918
21021
  if (persona) discovered[persona] = a.name;
20919
21022
  }
20920
- const loaderPath = path25.join(args.contentDir, "targets/foundry/brain-loader.md");
21023
+ const loaderPath = path26.join(args.contentDir, "targets/foundry/brain-loader.md");
20921
21024
  return {
20922
21025
  async applyPersona(a, ctx) {
20923
21026
  const personaName = a.personaName;
@@ -20933,7 +21036,7 @@ async function buildConvergeDeps(args) {
20933
21036
  return applyPersona(a, ctx, {
20934
21037
  agentName,
20935
21038
  project: args.project,
20936
- personaDir: path25.join(ctx.contentDir, personaItem.path),
21039
+ personaDir: path26.join(ctx.contentDir, personaItem.path),
20937
21040
  loaderPath
20938
21041
  });
20939
21042
  },
@@ -21007,18 +21110,23 @@ async function buildConvergeDeps(args) {
21007
21110
  await awaitAgentQueryable({ credential: args.credential, projectEndpoint: args.project.endpoint, agentName, onProgress: args.onProgress });
21008
21111
  }
21009
21112
  if (args.gatewayUrl) {
21010
- try {
21011
- const res = await fetch(`${args.gatewayUrl}/api/version`, { method: "GET" });
21012
- if (res.ok) {
21013
- const body = await res.json().catch(() => ({}));
21014
- args.onProgress?.(`gateway reachable (version: ${body.version ?? "unknown"}).`);
21015
- } else if (res.status === 401 || res.status === 403) {
21016
- args.onProgress?.(`gateway reachable (auth-gated, HTTP ${res.status.toString()}).`);
21017
- } else {
21018
- warn(`gateway health probe returned HTTP ${res.status.toString()} \u2014 not treated as fatal.`);
21019
- }
21020
- } catch (e) {
21021
- warn(`gateway health probe failed: ${e.message} \u2014 not treated as fatal.`);
21113
+ const read = await readGatewayVersion(args.gatewayUrl);
21114
+ switch (read.kind) {
21115
+ case "version":
21116
+ args.onProgress?.(`gateway reachable (version: ${read.version}).`);
21117
+ break;
21118
+ case "no-version":
21119
+ args.onProgress?.("gateway reachable (version: unknown).");
21120
+ break;
21121
+ case "auth-gated":
21122
+ args.onProgress?.(`gateway reachable (auth-gated, HTTP ${read.status.toString()}).`);
21123
+ break;
21124
+ case "http-error":
21125
+ warn(`gateway health probe returned HTTP ${read.status.toString()} \u2014 not treated as fatal.`);
21126
+ break;
21127
+ case "unreachable":
21128
+ warn(`gateway health probe failed: ${read.detail} \u2014 not treated as fatal.`);
21129
+ break;
21022
21130
  }
21023
21131
  }
21024
21132
  },
@@ -21363,14 +21471,14 @@ async function patchApplyRequest(client, mutate) {
21363
21471
 
21364
21472
  // src/lib/platform-self-update.ts
21365
21473
  import * as fs25 from "fs";
21366
- import * as path26 from "path";
21474
+ import * as path27 from "path";
21367
21475
  function toVTag2(v) {
21368
21476
  return v.startsWith("v") ? v : `v${v}`;
21369
21477
  }
21370
21478
  function readBakedReleaseVersion(repoRoot) {
21371
21479
  if (!repoRoot) return null;
21372
21480
  try {
21373
- const raw = fs25.readFileSync(path26.join(repoRoot, "installer", "version.json"), "utf8");
21481
+ const raw = fs25.readFileSync(path27.join(repoRoot, "installer", "version.json"), "utf8");
21374
21482
  const v = JSON.parse(raw).version;
21375
21483
  return typeof v === "string" && v.length > 0 ? v : null;
21376
21484
  } catch {
@@ -21515,17 +21623,20 @@ async function reconvergeToPrevious(args, previousVersion) {
21515
21623
  await applyPlan(rollbackPlan, args.deps, rollbackCtx);
21516
21624
  }
21517
21625
  async function defaultGatewayProbe(gatewayUrl, expected) {
21518
- try {
21519
- const res = await fetch(`${gatewayUrl}/api/version`, { method: "GET" });
21520
- if (res.status === 401 || res.status === 403) return { ok: true };
21521
- if (!res.ok) return { ok: false, detail: `gateway /api/version returned HTTP ${res.status.toString()}` };
21522
- const body = await res.json().catch(() => ({}));
21523
- if (body.version && !versionMatches(body.version, expected)) {
21524
- return { ok: false, detail: `gateway reports version '${body.version}', expected '${expected}'` };
21525
- }
21526
- return { ok: true };
21527
- } catch (e) {
21528
- return { ok: false, detail: `gateway unreachable: ${e.message}` };
21626
+ const read = await readGatewayVersion(gatewayUrl);
21627
+ switch (read.kind) {
21628
+ case "unreachable":
21629
+ return { ok: false, detail: `gateway unreachable: ${read.detail}` };
21630
+ case "http-error":
21631
+ return { ok: false, detail: `gateway /api/version returned HTTP ${read.status.toString()}` };
21632
+ case "auth-gated":
21633
+ case "no-version":
21634
+ return { ok: true };
21635
+ case "version":
21636
+ return versionMatches(read.version, expected) ? { ok: true } : {
21637
+ ok: true,
21638
+ detail: `gateway reports version '${read.version}', target '${expected}' \u2014 recorded, not gated (see defaultGatewayProbe)`
21639
+ };
21529
21640
  }
21530
21641
  }
21531
21642
  function versionMatches(running, expected) {
@@ -21787,7 +21898,7 @@ function targetManifestSource(ctx, target) {
21787
21898
  }
21788
21899
 
21789
21900
  // src/commands/platform/seed-stamp.ts
21790
- import { readFileSync as readFileSync17 } from "fs";
21901
+ import { readFileSync as readFileSync18 } from "fs";
21791
21902
  import { Command as Command35, Option as Option32 } from "clipanion";
21792
21903
  import { DefaultAzureCredential as DefaultAzureCredential18, ManagedIdentityCredential as ManagedIdentityCredential2 } from "@azure/identity";
21793
21904
  init_errors();
@@ -21874,7 +21985,7 @@ function buildSeedStamp(d, cliVersion, nowIso) {
21874
21985
 
21875
21986
  // src/commands/platform/seed-stamp.ts
21876
21987
  async function seedStamp2(args) {
21877
- const readFileImpl = args.readFileImpl ?? ((p) => readFileSync17(p, "utf8"));
21988
+ const readFileImpl = args.readFileImpl ?? ((p) => readFileSync18(p, "utf8"));
21878
21989
  const readStampImpl = args.readStampImpl ?? readStamp;
21879
21990
  const writeStampImpl = args.writeStampImpl ?? ((stamp2, o) => writeStamp({ ...o, stamp: stamp2 }));
21880
21991
  const discoverImpl = args.discoverImpl ?? discoverStampStorage;
@@ -22752,7 +22863,7 @@ async function patchRedirectUris(appObjectId, fqdn) {
22752
22863
  init_errors();
22753
22864
 
22754
22865
  // src/lib/whatif.ts
22755
- import * as path27 from "path";
22866
+ import * as path28 from "path";
22756
22867
 
22757
22868
  // src/lib/identifier-patterns.ts
22758
22869
  var IDENTIFIER_PATTERNS = [
@@ -22808,7 +22919,7 @@ function deriveResourceType(resourceId) {
22808
22919
  return parts.join("/");
22809
22920
  }
22810
22921
  async function runWhatIf(opts) {
22811
- const bicepPath = path27.join(opts.repoRoot, "deploy", "main.bicep");
22922
+ const bicepPath = path28.join(opts.repoRoot, "deploy", "main.bicep");
22812
22923
  const out = await runAz([
22813
22924
  "deployment",
22814
22925
  "group",
@@ -22906,9 +23017,9 @@ function flattenDelta(delta, prefix = "") {
22906
23017
  const out = [];
22907
23018
  for (const d of delta) {
22908
23019
  const segment = /^[0-9]+$/.test(d.path) ? `[${d.path}]` : prefix ? `.${d.path}` : d.path;
22909
- const path42 = prefix ? `${prefix}${segment}` : d.path;
22910
- if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children, path42));
22911
- else out.push({ ...d, path: path42 });
23020
+ const path43 = prefix ? `${prefix}${segment}` : d.path;
23021
+ if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children, path43));
23022
+ else out.push({ ...d, path: path43 });
22912
23023
  }
22913
23024
  return out;
22914
23025
  }
@@ -23271,7 +23382,7 @@ var EvalSkillCommand = class extends M8tCommand {
23271
23382
 
23272
23383
  // src/commands/eval/exam.ts
23273
23384
  import { spawnSync as spawnSync5 } from "child_process";
23274
- import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync18, existsSync as existsSync15, readdirSync as readdirSync2 } from "fs";
23385
+ import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync19, existsSync as existsSync16, readdirSync as readdirSync2 } from "fs";
23275
23386
  import { join as join27 } from "path";
23276
23387
  import { Command as Command42, Option as Option39 } from "clipanion";
23277
23388
  init_errors();
@@ -23454,10 +23565,10 @@ function resolveRefereeHome(refereeHomeOut, env) {
23454
23565
  return null;
23455
23566
  }
23456
23567
  function resolveTaskSetDir(base, worker, version) {
23457
- if (existsSync15(join27(base, version))) return version;
23568
+ if (existsSync16(join27(base, version))) return version;
23458
23569
  const prefixed = `${worker}-${version}`;
23459
- if (existsSync15(join27(base, prefixed))) return prefixed;
23460
- if (version === "latest" && existsSync15(base)) {
23570
+ if (existsSync16(join27(base, prefixed))) return prefixed;
23571
+ if (version === "latest" && existsSync16(base)) {
23461
23572
  const dirs = readdirSync2(base, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.startsWith(`${worker}-`)).map((d) => d.name).sort();
23462
23573
  if (dirs.length > 0) return dirs[dirs.length - 1];
23463
23574
  }
@@ -23476,7 +23587,7 @@ function readSealedTaskIds(taskSetVersion, refereeHomeOut, env = process.env) {
23476
23587
  const manifestPath = join27(home, "tasksets", worker, versionDir, "manifest.yaml");
23477
23588
  let text;
23478
23589
  try {
23479
- text = readFileSync18(manifestPath, "utf-8");
23590
+ text = readFileSync19(manifestPath, "utf-8");
23480
23591
  } catch (e) {
23481
23592
  throw new LocalCliError({
23482
23593
  code: "EXAM_REDACTION_UNSAFE",
@@ -23864,7 +23975,7 @@ import { Command as Command46, Option as Option43 } from "clipanion";
23864
23975
  import { DefaultAzureCredential as DefaultAzureCredential22 } from "@azure/identity";
23865
23976
  import * as fs26 from "fs";
23866
23977
  import * as os11 from "os";
23867
- import * as path28 from "path";
23978
+ import * as path29 from "path";
23868
23979
 
23869
23980
  // src/lib/doctor-checks.ts
23870
23981
  function checkAzSignedIn(az) {
@@ -24343,7 +24454,7 @@ async function resolveAccountLocation(accountId) {
24343
24454
  }
24344
24455
  }
24345
24456
  function probeRepoRoot() {
24346
- const marker = path28.join(os11.homedir(), ".m8t", "repo-root");
24457
+ const marker = path29.join(os11.homedir(), ".m8t", "repo-root");
24347
24458
  if (!fs26.existsSync(marker)) {
24348
24459
  return { markerExists: false, path: null, isDir: false, isGitCheckout: false };
24349
24460
  }
@@ -24360,13 +24471,13 @@ function probeRepoRoot() {
24360
24471
  } catch {
24361
24472
  isDir = false;
24362
24473
  }
24363
- const isGitCheckout = isDir && fs26.existsSync(path28.join(repoPath, ".git"));
24474
+ const isGitCheckout = isDir && fs26.existsSync(path29.join(repoPath, ".git"));
24364
24475
  return { markerExists: true, path: repoPath, isDir, isGitCheckout };
24365
24476
  }
24366
24477
  function probeLegacyStateDir() {
24367
24478
  return {
24368
- legacyExists: fs26.existsSync(path28.join(os11.homedir(), ".m8t-stack")),
24369
- currentExists: fs26.existsSync(path28.join(os11.homedir(), ".m8t"))
24479
+ legacyExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t-stack")),
24480
+ currentExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t"))
24370
24481
  };
24371
24482
  }
24372
24483
  var DoctorCommand = class extends M8tCommand {
@@ -25297,14 +25408,14 @@ import { Command as Command48, Option as Option45 } from "clipanion";
25297
25408
 
25298
25409
  // src/lib/profiles.ts
25299
25410
  import * as fs27 from "fs/promises";
25300
- import * as path29 from "path";
25411
+ import * as path30 from "path";
25301
25412
  import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
25302
25413
  function profilesDir() {
25303
25414
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
25304
- return path29.join(home, ".m8t", "profiles");
25415
+ return path30.join(home, ".m8t", "profiles");
25305
25416
  }
25306
25417
  function getProfilePath(name) {
25307
- return path29.join(profilesDir(), `${path29.basename(name)}.yaml`);
25418
+ return path30.join(profilesDir(), `${path30.basename(name)}.yaml`);
25308
25419
  }
25309
25420
  function slugifyTenant(domainOrId) {
25310
25421
  const base = domainOrId.split(".")[0].toLowerCase();
@@ -26580,7 +26691,7 @@ function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedT
26580
26691
  // ../../packages/brain/engine/dist/esm/dream/writer.js
26581
26692
  var API2 = "https://api.github.com";
26582
26693
  var WRITER_ALLOWED_PREFIX = /^(memory|inbox|quarantine|artifacts)\//;
26583
- var isAllowedWritePath = (path42, allowedPrefix) => allowedPrefix.test(path42) && !path42.split("/").includes("..");
26694
+ var isAllowedWritePath = (path43, allowedPrefix) => allowedPrefix.test(path43) && !path43.split("/").includes("..");
26584
26695
  var unquote = (s) => s.trim().replace(/^["']|["']$/g, "");
26585
26696
  function parseFrontmatter(content) {
26586
26697
  const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
@@ -26623,8 +26734,8 @@ function makeGitDataWriter(args) {
26623
26734
  if (args.allowedPathPrefix && !args.allowedPathPrefix.source.startsWith("^")) {
26624
26735
  throw new Error(`makeGitDataWriter: allowedPathPrefix must be anchored with "^" (got /${args.allowedPathPrefix.source}/) \u2014 an unanchored regex would widen the B1 write-path allowlist`);
26625
26736
  }
26626
- async function gh(token, method, path42, body) {
26627
- const res = await doFetch(`${API2}/repos/${repoPath}${path42}`, {
26737
+ async function gh(token, method, path43, body) {
26738
+ const res = await doFetch(`${API2}/repos/${repoPath}${path43}`, {
26628
26739
  method,
26629
26740
  headers: {
26630
26741
  Authorization: `Bearer ${token}`,
@@ -26637,8 +26748,8 @@ function makeGitDataWriter(args) {
26637
26748
  const text = await res.text();
26638
26749
  return { status: res.status, ok: res.ok, json: text ? JSON.parse(text) : {} };
26639
26750
  }
26640
- async function readFileWith(token, path42) {
26641
- const encodedPath = path42.split("/").map(encodeURIComponent).join("/");
26751
+ async function readFileWith(token, path43) {
26752
+ const encodedPath = path43.split("/").map(encodeURIComponent).join("/");
26642
26753
  const r = await gh(token, "GET", `/contents/${encodedPath}?ref=${args.branch}`);
26643
26754
  if (r.status === 404)
26644
26755
  return null;
@@ -26654,9 +26765,9 @@ function makeGitDataWriter(args) {
26654
26765
  throw new Error(`fetchTip: HTTP ${String(r.status)}`);
26655
26766
  return r.json.object.sha;
26656
26767
  },
26657
- async readFile(path42) {
26768
+ async readFile(path43) {
26658
26769
  const token = await args.mintToken();
26659
- return readFileWith(token, path42);
26770
+ return readFileWith(token, path43);
26660
26771
  },
26661
26772
  async listMemory() {
26662
26773
  const token = await args.mintToken();
@@ -26665,9 +26776,9 @@ function makeGitDataWriter(args) {
26665
26776
  return [];
26666
26777
  const paths = r.json.tree.filter((e) => e.type === "blob" && e.path.startsWith("memory/") && e.path.endsWith(".md")).map((e) => e.path);
26667
26778
  const out = [];
26668
- for (const path42 of paths) {
26669
- const content = await readFileWith(token, path42);
26670
- out.push({ path: path42, frontmatter: content ? parseFrontmatter(content) : {} });
26779
+ for (const path43 of paths) {
26780
+ const content = await readFileWith(token, path43);
26781
+ out.push({ path: path43, frontmatter: content ? parseFrontmatter(content) : {} });
26671
26782
  }
26672
26783
  return out;
26673
26784
  },
@@ -27106,7 +27217,7 @@ async function loadMemoryContext(brain) {
27106
27217
  return {
27107
27218
  files,
27108
27219
  indexEntries,
27109
- originOf: (path42) => originByPath.get(path42) ?? "worker"
27220
+ originOf: (path43) => originByPath.get(path43) ?? "worker"
27110
27221
  };
27111
27222
  }
27112
27223
 
@@ -27127,14 +27238,14 @@ function checkEvidenceMembership(delta, harvested) {
27127
27238
  }
27128
27239
  var BatchAbort = class extends Error {
27129
27240
  path;
27130
- constructor(path42, message) {
27241
+ constructor(path43, message) {
27131
27242
  super(message);
27132
- this.path = path42;
27243
+ this.path = path43;
27133
27244
  this.name = "BatchAbort";
27134
27245
  }
27135
27246
  };
27136
- var isIndexFile = (path42) => /(^|\/)[^/]*_index\.md$/.test(path42);
27137
- var isMemoryIndex = (path42) => path42 === "memory/MEMORY.md";
27247
+ var isIndexFile = (path43) => /(^|\/)[^/]*_index\.md$/.test(path43);
27248
+ var isMemoryIndex = (path43) => path43 === "memory/MEMORY.md";
27138
27249
  function targetPath(delta) {
27139
27250
  switch (delta.verb) {
27140
27251
  case "new":
@@ -27151,29 +27262,29 @@ function targetPath(delta) {
27151
27262
  }
27152
27263
  async function checkOriginTier(delta, lookup) {
27153
27264
  const evidence = evidenceOf(delta) ?? [];
27154
- const path42 = targetPath(delta);
27155
- if (path42 === null)
27265
+ const path43 = targetPath(delta);
27266
+ if (path43 === null)
27156
27267
  return { ok: true };
27157
- if (isIndexFile(path42) && !isMemoryIndex(path42)) {
27158
- return { ok: false, flagged: { kind: "flagged", path: path42, tension: `refused: ${path42} is an index file (only memory/MEMORY.md is editable)`, evidence } };
27268
+ if (isIndexFile(path43) && !isMemoryIndex(path43)) {
27269
+ return { ok: false, flagged: { kind: "flagged", path: path43, tension: `refused: ${path43} is an index file (only memory/MEMORY.md is editable)`, evidence } };
27159
27270
  }
27160
- const target = await lookup(path42);
27161
- const isStructural = path42.startsWith("references/");
27271
+ const target = await lookup(path43);
27272
+ const isStructural = path43.startsWith("references/");
27162
27273
  const origin = target?.frontmatter.origin ?? (isStructural ? "operator" : "worker");
27163
27274
  const editable = origin === "worker" || origin === "dream";
27164
27275
  if (editable)
27165
27276
  return { ok: true };
27166
27277
  const removesOperatorTarget = delta.verb === "retract" || delta.verb === "supersede" && delta.oldPath !== delta.newPath;
27167
27278
  if (removesOperatorTarget) {
27168
- throw new BatchAbort(path42, `supersede/retract OLD target ${path42} is origin: ${origin} \u2014 aborting batch (never half-apply)`);
27279
+ throw new BatchAbort(path43, `supersede/retract OLD target ${path43} is origin: ${origin} \u2014 aborting batch (never half-apply)`);
27169
27280
  }
27170
- return { ok: false, flagged: { kind: "flagged", path: path42, tension: `operator-origin (${origin}); flag-only`, evidence } };
27281
+ return { ok: false, flagged: { kind: "flagged", path: path43, tension: `operator-origin (${origin}); flag-only`, evidence } };
27171
27282
  }
27172
27283
  var ALLOWED_MEMORY = /^memory\/.+\.md$/;
27173
27284
  var ALLOWED_INBOX = /^inbox\//;
27174
27285
  var ALLOWED_QUARANTINE = /^quarantine\//;
27175
27286
  var ALLOWED_FLAG = /^memory\//;
27176
- var hasTraversal = (path42) => path42.split("/").includes("..");
27287
+ var hasTraversal = (path43) => path43.split("/").includes("..");
27177
27288
  function checkPathAllowed(delta) {
27178
27289
  const evidence = evidenceOf(delta) ?? [];
27179
27290
  const reject = (detail) => ({ ok: false, rejected: { kind: "rejected", detail, evidence } });
@@ -27280,7 +27391,7 @@ ${inject}
27280
27391
  ---
27281
27392
  ` + body.slice(m[0].length);
27282
27393
  }
27283
- var indexLine = (path42, title, date, tags) => `- \`${path42}\` \u2014 **${title}**: ${title}. (${date} \xB7 ${tags.join(", ")})`;
27394
+ var indexLine = (path43, title, date, tags) => `- \`${path43}\` \u2014 **${title}**: ${title}. (${date} \xB7 ${tags.join(", ")})`;
27284
27395
  function splitIndex(index) {
27285
27396
  const all = index.split("\n");
27286
27397
  const firstLineIdx = all.findIndex((l) => l.startsWith("- `memory/"));
@@ -27453,16 +27564,16 @@ function defaultDreamSeams(opts = {}) {
27453
27564
  const mem = await memory(deps.brain);
27454
27565
  const harvested = harvestedIds(input);
27455
27566
  const ctx = { readFile: (p) => deps.brain.readFile(p), at: deps.clock() };
27456
- const lookup = (path42) => Promise.resolve(mem.files.find((f) => f.path === path42) ?? null);
27567
+ const lookup = (path43) => Promise.resolve(mem.files.find((f) => f.path === path43) ?? null);
27457
27568
  const digest = [...pendingRejected];
27458
27569
  let changes = [];
27459
27570
  let indexEdit;
27460
27571
  try {
27461
27572
  for (const raw of deltas) {
27462
27573
  const delta = forcePolicyQuarantine(raw);
27463
- const path42 = checkPathAllowed(delta);
27464
- if (!path42.ok) {
27465
- digest.push(path42.rejected);
27574
+ const path43 = checkPathAllowed(delta);
27575
+ if (!path43.ok) {
27576
+ digest.push(path43.rejected);
27466
27577
  continue;
27467
27578
  }
27468
27579
  const ev = checkEvidenceMembership(delta, harvested);
@@ -28590,9 +28701,9 @@ var DISCLOSURE_TIER1 = "Operational data. To support your installation, m8t rece
28590
28701
 
28591
28702
  // ../../packages/telemetry-contract/src/endpoints.ts
28592
28703
  var INGEST_BASE_URL = (process.env.M8T_INGEST_BASE_URL ?? "").trim() || "https://m8t-admin.wonderfuldesert-721e332f.eastus2.azurecontainerapps.io";
28593
- function ingestUrl(path42) {
28704
+ function ingestUrl(path43) {
28594
28705
  const base = INGEST_BASE_URL.replace(/\/+$/, "");
28595
- return `${base}${path42.startsWith("/") ? path42 : `/${path42}`}`;
28706
+ return `${base}${path43.startsWith("/") ? path43 : `/${path43}`}`;
28596
28707
  }
28597
28708
 
28598
28709
  // src/commands/bootstrap/preflight.ts
@@ -28726,7 +28837,7 @@ ${colors.error(" " + why)}
28726
28837
  // src/commands/bootstrap/launch.ts
28727
28838
  import * as fs30 from "fs";
28728
28839
  import * as os14 from "os";
28729
- import * as path32 from "path";
28840
+ import * as path33 from "path";
28730
28841
  import { Command as Command54, Option as Option51 } from "clipanion";
28731
28842
  init_errors();
28732
28843
 
@@ -28885,7 +28996,7 @@ async function kickInstaller(s) {
28885
28996
  import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
28886
28997
  import * as fs28 from "fs/promises";
28887
28998
  import * as os12 from "os";
28888
- import * as path30 from "path";
28999
+ import * as path31 from "path";
28889
29000
  init_errors();
28890
29001
  var STATUS_CONTAINER = "status";
28891
29002
  var STATUS_BLOB = "status.json";
@@ -28924,7 +29035,7 @@ async function readStatusBlob(opts) {
28924
29035
  cause: e
28925
29036
  });
28926
29037
  }
28927
- const tmpFile = path30.join(os12.tmpdir(), `m8t-status-${randomUUID2()}.json`);
29038
+ const tmpFile = path31.join(os12.tmpdir(), `m8t-status-${randomUUID2()}.json`);
28928
29039
  try {
28929
29040
  await runAz([
28930
29041
  "storage",
@@ -28960,12 +29071,12 @@ async function readStatusBlob(opts) {
28960
29071
  // src/lib/bootstrap-state.ts
28961
29072
  import * as fs29 from "fs/promises";
28962
29073
  import * as os13 from "os";
28963
- import * as path31 from "path";
29074
+ import * as path32 from "path";
28964
29075
  function stateDir(home) {
28965
- return path31.join(home, ".m8t");
29076
+ return path32.join(home, ".m8t");
28966
29077
  }
28967
29078
  function statePath(home) {
28968
- return path31.join(stateDir(home), "bootstrap.json");
29079
+ return path32.join(stateDir(home), "bootstrap.json");
28969
29080
  }
28970
29081
  async function readBootstrapState(home = os13.homedir()) {
28971
29082
  try {
@@ -29166,7 +29277,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29166
29277
  `);
29167
29278
  return 0;
29168
29279
  }
29169
- const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path32.join(os14.homedir(), ".m8t", "github-app.json");
29280
+ const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path33.join(os14.homedir(), ".m8t", "github-app.json");
29170
29281
  const skipBrains = this.noBrains === true;
29171
29282
  const requestedOrg = typeof this.org === "string" ? this.org : void 0;
29172
29283
  let githubApp;
@@ -29316,13 +29427,13 @@ async function getAciState(opts) {
29316
29427
  // src/lib/bootstrap-finalize.ts
29317
29428
  import * as fs34 from "fs/promises";
29318
29429
  import * as os18 from "os";
29319
- import * as path38 from "path";
29430
+ import * as path39 from "path";
29320
29431
 
29321
29432
  // src/lib/company-profile-seed.ts
29322
29433
  import { spawn as spawn6 } from "child_process";
29323
- import { closeSync, openSync, readFileSync as readFileSync21 } from "fs";
29434
+ import { closeSync, openSync, readFileSync as readFileSync22 } from "fs";
29324
29435
  import * as os15 from "os";
29325
- import * as path33 from "path";
29436
+ import * as path34 from "path";
29326
29437
  init_errors();
29327
29438
 
29328
29439
  // src/lib/onboarding-profile.ts
@@ -30047,9 +30158,9 @@ function composeFounderIdentityNote(id) {
30047
30158
 
30048
30159
  // src/lib/company-profile-seed.ts
30049
30160
  function readGithubAppCreds(credsPath) {
30050
- const p = credsPath ?? path33.join(os15.homedir(), ".m8t", "github-app.json");
30161
+ const p = credsPath ?? path34.join(os15.homedir(), ".m8t", "github-app.json");
30051
30162
  try {
30052
- return JSON.parse(readFileSync21(p, "utf8"));
30163
+ return JSON.parse(readFileSync22(p, "utf8"));
30053
30164
  } catch {
30054
30165
  return null;
30055
30166
  }
@@ -30115,7 +30226,7 @@ function upsertMemoryIndexOnce(existing, line2, targetPath2) {
30115
30226
  async function applyProfileToBrain(args) {
30116
30227
  const token = await mintInstallationTokenFromPem({
30117
30228
  appId: args.appCreds.appId,
30118
- privateKeyPem: readFileSync21(args.appCreds.pemPath, "utf8"),
30229
+ privateKeyPem: readFileSync22(args.appCreds.pemPath, "utf8"),
30119
30230
  installationId: args.appCreds.installationId,
30120
30231
  fetchImpl: args.fetchImpl
30121
30232
  });
@@ -30205,7 +30316,7 @@ async function applyProfileToBrains(args) {
30205
30316
  }
30206
30317
  }
30207
30318
  function spawnDetachedSeedWatch() {
30208
- const logPath = path33.join(os15.homedir(), ".m8t", "seed-profile.log");
30319
+ const logPath = path34.join(os15.homedir(), ".m8t", "seed-profile.log");
30209
30320
  const fd = openSync(logPath, "a");
30210
30321
  try {
30211
30322
  const child = spawn6(process.execPath, [process.argv[1] ?? "", "bootstrap", "seed-profile", "--watch"], {
@@ -30280,7 +30391,7 @@ function renderInstallSummary(args) {
30280
30391
  // src/lib/companion-install.ts
30281
30392
  import { constants as constants2 } from "fs";
30282
30393
  import * as fs32 from "fs/promises";
30283
- import * as path35 from "path";
30394
+ import * as path36 from "path";
30284
30395
  import { randomUUID as randomUUID3 } from "crypto";
30285
30396
  import { execFile, spawn as spawn7 } from "child_process";
30286
30397
 
@@ -30288,7 +30399,7 @@ import { execFile, spawn as spawn7 } from "child_process";
30288
30399
  import { createHash as createHash5 } from "crypto";
30289
30400
  import { constants } from "fs";
30290
30401
  import * as fs31 from "fs/promises";
30291
- import * as path34 from "path";
30402
+ import * as path35 from "path";
30292
30403
  var SHA256 = /^[a-f0-9]{64}$/u;
30293
30404
  var VERSION2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/u;
30294
30405
  function exactKeys(value, expected) {
@@ -30296,23 +30407,23 @@ function exactKeys(value, expected) {
30296
30407
  return actual.length === expected.length && actual.every((key2, index) => key2 === [...expected].sort()[index]);
30297
30408
  }
30298
30409
  function normalizedRelative(value) {
30299
- if (value.length === 0 || value.includes("\\") || value.includes("\0") || path34.posix.isAbsolute(value)) {
30410
+ if (value.length === 0 || value.includes("\\") || value.includes("\0") || path35.posix.isAbsolute(value)) {
30300
30411
  throw new Error("Artifact path must be a normalized relative POSIX path");
30301
30412
  }
30302
- const normalized = path34.posix.normalize(value);
30413
+ const normalized = path35.posix.normalize(value);
30303
30414
  if (normalized !== value || normalized === "." || normalized === ".." || normalized.startsWith("../")) {
30304
30415
  throw new Error("Artifact path escapes the payload root");
30305
30416
  }
30306
30417
  return value;
30307
30418
  }
30308
30419
  function validateLink(entryPath, target) {
30309
- if (target.length === 0 || target.includes("\\") || target.includes("\0") || path34.posix.isAbsolute(target)) {
30420
+ if (target.length === 0 || target.includes("\\") || target.includes("\0") || path35.posix.isAbsolute(target)) {
30310
30421
  throw new Error("Artifact symlink target must be relative");
30311
30422
  }
30312
- const resolved = path34.posix.normalize(
30313
- path34.posix.join(path34.posix.dirname(entryPath), target)
30423
+ const resolved = path35.posix.normalize(
30424
+ path35.posix.join(path35.posix.dirname(entryPath), target)
30314
30425
  );
30315
- if (resolved === ".." || resolved.startsWith("../") || path34.posix.isAbsolute(resolved)) {
30426
+ if (resolved === ".." || resolved.startsWith("../") || path35.posix.isAbsolute(resolved)) {
30316
30427
  throw new Error("Artifact symlink target escapes the payload root");
30317
30428
  }
30318
30429
  return target;
@@ -30396,13 +30507,13 @@ async function sha256File2(filePath) {
30396
30507
  return createHash5("sha256").update(await fs31.readFile(filePath)).digest("hex");
30397
30508
  }
30398
30509
  async function walk(root, relative3 = "") {
30399
- const directory = path34.join(root, ...relative3.split("/").filter(Boolean));
30510
+ const directory = path35.join(root, ...relative3.split("/").filter(Boolean));
30400
30511
  const children = await fs31.readdir(directory, { withFileTypes: true });
30401
30512
  const entries = [];
30402
30513
  for (const child of children.sort((left, right) => left.name.localeCompare(right.name))) {
30403
30514
  const childRelative = relative3 ? `${relative3}/${child.name}` : child.name;
30404
30515
  normalizedRelative(childRelative);
30405
- const childPath = path34.join(directory, child.name);
30516
+ const childPath = path35.join(directory, child.name);
30406
30517
  const stat5 = await fs31.lstat(childPath);
30407
30518
  if (stat5.isDirectory()) {
30408
30519
  entries.push(...await walk(root, childRelative));
@@ -30437,10 +30548,10 @@ async function validateResolvedLinks(root, entries) {
30437
30548
  for (const entry of entries) {
30438
30549
  if (entry.type !== "symlink") continue;
30439
30550
  try {
30440
- const linkPath = path34.join(root, ...entry.path.split("/"));
30551
+ const linkPath = path35.join(root, ...entry.path.split("/"));
30441
30552
  const resolved = await fs31.realpath(linkPath);
30442
- const relative3 = path34.relative(realRoot, resolved);
30443
- if (relative3 === ".." || relative3.startsWith(`..${path34.sep}`) || path34.isAbsolute(relative3)) {
30553
+ const relative3 = path35.relative(realRoot, resolved);
30554
+ if (relative3 === ".." || relative3.startsWith(`..${path35.sep}`) || path35.isAbsolute(relative3)) {
30444
30555
  throw new Error("Artifact symlink chain escapes the payload root");
30445
30556
  }
30446
30557
  } catch (error) {
@@ -30493,9 +30604,9 @@ async function readArtifactManifest(manifestPath) {
30493
30604
  }
30494
30605
  }
30495
30606
  function ensureContainedEntry(root, entryPath) {
30496
- const absolute = path34.join(root, ...entryPath.split("/"));
30497
- const relative3 = path34.relative(root, absolute);
30498
- if (relative3.startsWith("..") || path34.isAbsolute(relative3)) {
30607
+ const absolute = path35.join(root, ...entryPath.split("/"));
30608
+ const relative3 = path35.relative(root, absolute);
30609
+ if (relative3.startsWith("..") || path35.isAbsolute(relative3)) {
30499
30610
  throw new Error("Artifact entry escapes payload root");
30500
30611
  }
30501
30612
  return absolute;
@@ -30549,7 +30660,7 @@ async function copyArtifactPayload(sourceRoot, targetRoot, manifest) {
30549
30660
  for (const entry of manifest.entries) {
30550
30661
  const source = ensureContainedEntry(sourceRoot, entry.path);
30551
30662
  const target = ensureContainedEntry(targetRoot, entry.path);
30552
- await fs31.mkdir(path34.dirname(target), { recursive: true, mode: 448 });
30663
+ await fs31.mkdir(path35.dirname(target), { recursive: true, mode: 448 });
30553
30664
  if (entry.type === "file") {
30554
30665
  await fs31.copyFile(source, target);
30555
30666
  await fs31.chmod(target, entry.mode);
@@ -30593,8 +30704,8 @@ function execFileOutput(file, args) {
30593
30704
  }
30594
30705
  async function setCompanionStartAtLogin(input) {
30595
30706
  if (input.platform === "darwin") {
30596
- const launchAgents = path35.join(input.homeDirectory, "Library", "LaunchAgents");
30597
- const registration = path35.join(
30707
+ const launchAgents = path36.join(input.homeDirectory, "Library", "LaunchAgents");
30708
+ const registration = path36.join(
30598
30709
  launchAgents,
30599
30710
  "com.m8t.companion.plist"
30600
30711
  );
@@ -30655,7 +30766,7 @@ async function setCompanionStartAtLogin(input) {
30655
30766
  }
30656
30767
  async function getCompanionStartAtLogin(input) {
30657
30768
  if (input.platform === "darwin") {
30658
- const registration = path35.join(
30769
+ const registration = path36.join(
30659
30770
  input.homeDirectory,
30660
30771
  "Library",
30661
30772
  "LaunchAgents",
@@ -30717,26 +30828,26 @@ function assertSupported(options) {
30717
30828
  }
30718
30829
  function companionInstallPaths(options) {
30719
30830
  assertSupported(options);
30720
- const companionState = path35.join(
30831
+ const companionState = path36.join(
30721
30832
  options.homeDirectory,
30722
30833
  ".m8t",
30723
30834
  "companion"
30724
30835
  );
30725
- const targetRoot = options.platform === "darwin" ? path35.join(
30836
+ const targetRoot = options.platform === "darwin" ? path36.join(
30726
30837
  options.homeDirectory,
30727
30838
  "Applications",
30728
30839
  "m8t Companion.app"
30729
- ) : path35.join(
30730
- options.localAppData ?? path35.join(options.homeDirectory, "AppData", "Local"),
30840
+ ) : path36.join(
30841
+ options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local"),
30731
30842
  "m8t",
30732
30843
  "companion",
30733
30844
  "app"
30734
30845
  );
30735
30846
  return {
30736
30847
  targetRoot,
30737
- installManifest: path35.join(companionState, "install-v1.json"),
30738
- runtimeBinding: path35.join(companionState, "runtime-v1.json"),
30739
- preferences: path35.join(companionState, "preferences-v1.json")
30848
+ installManifest: path36.join(companionState, "install-v1.json"),
30849
+ runtimeBinding: path36.join(companionState, "runtime-v1.json"),
30850
+ preferences: path36.join(companionState, "preferences-v1.json")
30740
30851
  };
30741
30852
  }
30742
30853
  function exactKeys2(value, keys) {
@@ -30747,7 +30858,7 @@ function parseInstallManifest(value) {
30747
30858
  throw new Error("Install manifest schema is invalid");
30748
30859
  }
30749
30860
  const record = value;
30750
- if (!exactKeys2(record, INSTALL_KEYS) || record.schemaVersion !== 1 || typeof record.version !== "string" || record.platform !== "darwin" && record.platform !== "win32" || record.architecture !== "arm64" && record.architecture !== "x64" || typeof record.entryRelativePath !== "string" || typeof record.artifactTreeSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(record.artifactTreeSha256) || typeof record.ownedTargetRoot !== "string" || !path35.isAbsolute(record.ownedTargetRoot)) {
30861
+ if (!exactKeys2(record, INSTALL_KEYS) || record.schemaVersion !== 1 || typeof record.version !== "string" || record.platform !== "darwin" && record.platform !== "win32" || record.architecture !== "arm64" && record.architecture !== "x64" || typeof record.entryRelativePath !== "string" || typeof record.artifactTreeSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(record.artifactTreeSha256) || typeof record.ownedTargetRoot !== "string" || !path36.isAbsolute(record.ownedTargetRoot)) {
30751
30862
  throw new Error("Install manifest schema is invalid");
30752
30863
  }
30753
30864
  return record;
@@ -30757,7 +30868,7 @@ function parseRuntimeBinding(value, platform) {
30757
30868
  throw new Error("Runtime binding schema is invalid");
30758
30869
  }
30759
30870
  const record = value;
30760
- const paths = platform === "win32" ? path35.win32 : path35.posix;
30871
+ const paths = platform === "win32" ? path36.win32 : path36.posix;
30761
30872
  if (!exactKeys2(record, RUNTIME_KEYS) || record.schemaVersion !== 1 || typeof record.nodeExecutable !== "string" || !paths.isAbsolute(record.nodeExecutable) || typeof record.cliEntry !== "string" || !paths.isAbsolute(record.cliEntry) || typeof record.gatewayOrigin !== "string") {
30762
30873
  throw new Error("Runtime binding schema is invalid");
30763
30874
  }
@@ -30791,18 +30902,18 @@ async function assertNotSymlink(filePath, kind) {
30791
30902
  }
30792
30903
  }
30793
30904
  async function assertOwnedDirectoryChain(anchor, targetDirectory) {
30794
- const relative3 = path35.relative(anchor, targetDirectory);
30795
- if (relative3 === ".." || relative3.startsWith(`..${path35.sep}`) || path35.isAbsolute(relative3)) {
30905
+ const relative3 = path36.relative(anchor, targetDirectory);
30906
+ if (relative3 === ".." || relative3.startsWith(`..${path36.sep}`) || path36.isAbsolute(relative3)) {
30796
30907
  throw new Error("Companion owned directory escapes its trusted anchor");
30797
30908
  }
30798
- const segments = relative3.split(path35.sep).filter(Boolean);
30909
+ const segments = relative3.split(path36.sep).filter(Boolean);
30799
30910
  let current = anchor;
30800
30911
  const anchorStatus = await fs32.lstat(anchor);
30801
30912
  if (anchorStatus.isSymbolicLink() || !anchorStatus.isDirectory()) {
30802
30913
  throw new Error("Companion owned directory anchor is unsafe");
30803
30914
  }
30804
30915
  for (const segment of segments) {
30805
- current = path35.join(current, segment);
30916
+ current = path36.join(current, segment);
30806
30917
  try {
30807
30918
  const status = await fs32.lstat(current);
30808
30919
  if (status.isSymbolicLink() || !status.isDirectory()) {
@@ -30817,10 +30928,10 @@ async function assertOwnedDirectoryChain(anchor, targetDirectory) {
30817
30928
  async function assertOwnedParents(options, paths) {
30818
30929
  await assertOwnedDirectoryChain(
30819
30930
  options.homeDirectory,
30820
- path35.dirname(paths.installManifest)
30931
+ path36.dirname(paths.installManifest)
30821
30932
  );
30822
- const targetAnchor = options.platform === "win32" ? options.localAppData ?? path35.join(options.homeDirectory, "AppData", "Local") : options.homeDirectory;
30823
- await assertOwnedDirectoryChain(targetAnchor, path35.dirname(paths.targetRoot));
30933
+ const targetAnchor = options.platform === "win32" ? options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local") : options.homeDirectory;
30934
+ await assertOwnedDirectoryChain(targetAnchor, path36.dirname(paths.targetRoot));
30824
30935
  }
30825
30936
  async function readRegularText(filePath, maxBytes) {
30826
30937
  const before = await fs32.lstat(filePath);
@@ -30852,7 +30963,7 @@ async function atomicWriteJson(filePath, value) {
30852
30963
  }
30853
30964
  async function atomicWriteText(filePath, contents, mode) {
30854
30965
  await assertNotSymlink(filePath, "Companion state file");
30855
- await fs32.mkdir(path35.dirname(filePath), {
30966
+ await fs32.mkdir(path36.dirname(filePath), {
30856
30967
  recursive: true,
30857
30968
  mode: 448
30858
30969
  });
@@ -30969,7 +31080,7 @@ async function statusCompanion(options) {
30969
31080
  realRegularFile(runtime.nodeExecutable, options.platform !== "win32"),
30970
31081
  realRegularFile(runtime.cliEntry, false)
30971
31082
  ]);
30972
- const executable = path35.join(
31083
+ const executable = path36.join(
30973
31084
  paths.targetRoot,
30974
31085
  ...install.entryRelativePath.split("/")
30975
31086
  );
@@ -31017,8 +31128,8 @@ async function converge(options, force) {
31017
31128
  if (artifactManifest.platform !== options.platform || artifactManifest.architecture !== options.architecture) {
31018
31129
  throw new Error("Companion artifact does not match this OS and architecture");
31019
31130
  }
31020
- const payloadRoot = path35.join(
31021
- path35.dirname(options.artifactManifestPath),
31131
+ const payloadRoot = path36.join(
31132
+ path36.dirname(options.artifactManifestPath),
31022
31133
  "payload"
31023
31134
  );
31024
31135
  await verifyArtifactSource(payloadRoot, artifactManifest);
@@ -31038,7 +31149,7 @@ async function converge(options, force) {
31038
31149
  if (priorInstalled) {
31039
31150
  await assertCompanionNotRunning(
31040
31151
  options,
31041
- path35.join(
31152
+ path36.join(
31042
31153
  priorInstalled.paths.targetRoot,
31043
31154
  ...priorInstalled.install.entryRelativePath.split("/")
31044
31155
  )
@@ -31057,7 +31168,7 @@ async function converge(options, force) {
31057
31168
  const stage = `${paths.targetRoot}.m8t-stage-${randomUUID3()}`;
31058
31169
  const backup = `${paths.targetRoot}.m8t-backup-${randomUUID3()}`;
31059
31170
  const copy = options.copyPayload ?? copyArtifactPayload;
31060
- await fs32.mkdir(path35.dirname(paths.targetRoot), {
31171
+ await fs32.mkdir(path36.dirname(paths.targetRoot), {
31061
31172
  recursive: true,
31062
31173
  mode: 448
31063
31174
  });
@@ -31121,7 +31232,7 @@ async function converge(options, force) {
31121
31232
  await readClosedJson(paths.runtimeBinding),
31122
31233
  options.platform
31123
31234
  );
31124
- const executable = path35.join(
31235
+ const executable = path36.join(
31125
31236
  paths.targetRoot,
31126
31237
  ...artifactManifest.entryRelativePath.split("/")
31127
31238
  );
@@ -31131,7 +31242,7 @@ async function converge(options, force) {
31131
31242
  platform: options.platform,
31132
31243
  executable: ownedExecutable
31133
31244
  }));
31134
- priorLoginExecutable = priorInstalled ? path35.join(
31245
+ priorLoginExecutable = priorInstalled ? path36.join(
31135
31246
  priorInstalled.paths.targetRoot,
31136
31247
  ...priorInstalled.install.entryRelativePath.split("/")
31137
31248
  ) : executable;
@@ -31190,7 +31301,7 @@ async function uninstallCompanion(options) {
31190
31301
  if (install.ownedTargetRoot !== paths.targetRoot) {
31191
31302
  throw new Error("Refusing to remove a non-owned companion target");
31192
31303
  }
31193
- const executable = path35.join(
31304
+ const executable = path36.join(
31194
31305
  paths.targetRoot,
31195
31306
  ...install.entryRelativePath.split("/")
31196
31307
  );
@@ -31208,7 +31319,7 @@ async function uninstallCompanion(options) {
31208
31319
 
31209
31320
  // src/commands/companion/install.ts
31210
31321
  import * as os17 from "os";
31211
- import * as path37 from "path";
31322
+ import * as path38 from "path";
31212
31323
  import { Command as Command55, Option as Option52 } from "clipanion";
31213
31324
 
31214
31325
  // src/lib/companion-channel.ts
@@ -31228,7 +31339,7 @@ import { createHash as createHash6 } from "crypto";
31228
31339
  import { execFile as execFile2 } from "child_process";
31229
31340
  import * as fs33 from "fs/promises";
31230
31341
  import * as os16 from "os";
31231
- import * as path36 from "path";
31342
+ import * as path37 from "path";
31232
31343
  init_errors();
31233
31344
  var MAX_ASSET_BYTES = 512 * 1024 * 1024;
31234
31345
  function extractArchive(archive, into) {
@@ -31281,20 +31392,20 @@ async function downloadCompanionArtifact(component, deps = {}) {
31281
31392
  hint: "Nothing was unpacked. This is what a corrupted download or a substituted file looks like \u2014 retry, and report it if it persists."
31282
31393
  });
31283
31394
  }
31284
- const root = await (deps.makeTemporaryDirectory ?? (() => fs33.mkdtemp(path36.join(os16.tmpdir(), "m8t-companion-"))))();
31395
+ const root = await (deps.makeTemporaryDirectory ?? (() => fs33.mkdtemp(path37.join(os16.tmpdir(), "m8t-companion-"))))();
31285
31396
  const dispose = async () => {
31286
31397
  await fs33.rm(root, { recursive: true, force: true }).catch(() => void 0);
31287
31398
  };
31288
31399
  try {
31289
- const archive = path36.join(root, pinned.asset);
31400
+ const archive = path37.join(root, pinned.asset);
31290
31401
  await fs33.writeFile(archive, bytes, { mode: 384 });
31291
- const unpacked = path36.join(root, "unpacked");
31402
+ const unpacked = path37.join(root, "unpacked");
31292
31403
  await fs33.mkdir(unpacked, { recursive: false, mode: 448 });
31293
31404
  await (deps.extract ?? extractArchive)(archive, unpacked);
31294
31405
  await fs33.rm(archive, { force: true });
31295
31406
  return {
31296
31407
  version: component.version,
31297
- artifactManifestPath: path36.join(unpacked, "artifact-v1.json"),
31408
+ artifactManifestPath: path37.join(unpacked, "artifact-v1.json"),
31298
31409
  dispose
31299
31410
  };
31300
31411
  } catch (error) {
@@ -31325,7 +31436,7 @@ async function convergeCompanionFromChannel(converge2, options = {}) {
31325
31436
  let artifactManifestPath;
31326
31437
  let dispose = () => Promise.resolve();
31327
31438
  if (stagedDirectory !== void 0) {
31328
- artifactManifestPath = path37.resolve(stagedDirectory, "artifact-v1.json");
31439
+ artifactManifestPath = path38.resolve(stagedDirectory, "artifact-v1.json");
31329
31440
  } else {
31330
31441
  const release = await readCompanionRelease(
31331
31442
  platformVersion !== void 0 ? { channel: true, version: platformTag(platformVersion) } : { url: CHANNEL_LATEST_URL }
@@ -31403,7 +31514,7 @@ function resolveRepoRootMarker(args) {
31403
31514
  }
31404
31515
  async function looksLikeCheckout(dir) {
31405
31516
  try {
31406
- return (await fs34.stat(path38.join(dir, "brain-template"))).isDirectory();
31517
+ return (await fs34.stat(path39.join(dir, "brain-template"))).isDirectory();
31407
31518
  } catch {
31408
31519
  return false;
31409
31520
  }
@@ -31422,8 +31533,8 @@ var defaultDeps2 = {
31422
31533
  homedir: () => os18.homedir()
31423
31534
  };
31424
31535
  async function finalizeInstall(args, deps = defaultDeps2) {
31425
- const markerDir = path38.join(deps.homedir(), ".m8t");
31426
- const markerPath = path38.join(markerDir, "repo-root");
31536
+ const markerDir = path39.join(deps.homedir(), ".m8t");
31537
+ const markerPath = path39.join(markerDir, "repo-root");
31427
31538
  const cwd = process.cwd();
31428
31539
  const existing = await fs34.readFile(markerPath, "utf8").then((s) => s.trim()).catch(() => null);
31429
31540
  const repoRoot = resolveRepoRootMarker({
@@ -31511,7 +31622,7 @@ async function finalizeInstall(args, deps = defaultDeps2) {
31511
31622
  }
31512
31623
  let brainOrg = null;
31513
31624
  try {
31514
- const credsRaw = await fs34.readFile(path38.join(markerDir, "github-app.json"), "utf8");
31625
+ const credsRaw = await fs34.readFile(path39.join(markerDir, "github-app.json"), "utf8");
31515
31626
  const creds = JSON.parse(credsRaw);
31516
31627
  brainOrg = typeof creds.org === "string" ? creds.org : null;
31517
31628
  } catch {
@@ -31942,7 +32053,7 @@ Found ${String(total)} orphaned assignment(s) (${breakdown}) (dry-run). ${colors
31942
32053
  // src/commands/bootstrap/ui.ts
31943
32054
  import * as fs36 from "fs";
31944
32055
  import * as os20 from "os";
31945
- import * as path40 from "path";
32056
+ import * as path41 from "path";
31946
32057
  import { Command as Command58, Option as Option55 } from "clipanion";
31947
32058
  import { DefaultAzureCredential as DefaultAzureCredential24 } from "@azure/identity";
31948
32059
  init_errors();
@@ -31951,7 +32062,7 @@ init_errors();
31951
32062
  import * as fs35 from "fs";
31952
32063
  import * as net from "net";
31953
32064
  import * as os19 from "os";
31954
- import * as path39 from "path";
32065
+ import * as path40 from "path";
31955
32066
  import { randomBytes as randomBytes3 } from "crypto";
31956
32067
  import { spawn as spawn8, spawnSync as spawnSync6 } from "child_process";
31957
32068
  init_errors();
@@ -32057,20 +32168,46 @@ async function deployIntakeAgentWithRetry(args) {
32057
32168
  }
32058
32169
  }
32059
32170
  }
32171
+ function renderNotReadyHint(resourceGroup, excluded) {
32172
+ const lines = ["Check 'm8t bootstrap status --watch' \u2014 the install may have stalled in foundry-create."];
32173
+ if (resourceGroup) {
32174
+ if (excluded.length > 0) {
32175
+ const count = excluded.length === 1 ? "1 project" : `${excluded.length.toString()} projects`;
32176
+ const verb = excluded.length === 1 ? "was" : "were";
32177
+ lines.push(
32178
+ `Discovery is scoped to this install's resource group (${resourceGroup}) on purpose, so it can`,
32179
+ `never deploy into someone else's project. ${count} elsewhere in this subscription ${verb}`,
32180
+ "skipped:",
32181
+ ...excluded.map((c) => ` ${c.endpoint}`)
32182
+ );
32183
+ }
32184
+ lines.push(
32185
+ "If ~/.m8t/bootstrap.json names a different install than the one you meant, re-run with",
32186
+ "--endpoint <projectEndpoint>."
32187
+ );
32188
+ }
32189
+ return lines.join("\n");
32190
+ }
32060
32191
  async function resolveFoundryEndpointWithWait(args, opts = {}) {
32061
32192
  const pollMs = opts.pollMs ?? 1e4;
32062
32193
  const timeoutMs = opts.timeoutMs ?? 15 * 6e4;
32063
32194
  const deadline = Date.now() + timeoutMs;
32195
+ let excluded = [];
32064
32196
  for (; ; ) {
32065
32197
  try {
32198
+ excluded = [];
32066
32199
  const p = await resolveFoundryProject({
32067
32200
  credential: args.credential,
32068
32201
  subscriptionId: args.subscriptionId,
32069
32202
  interactive: false,
32070
- // When the subscription holds multiple projects (e.g. a founder reinstalling
32071
- // alongside an existing platform), an explicit endpoint disambiguates instead
32072
- // of FOUNDRY_PROJECT_MULTIPLE. Omitted → single-project auto-discovery.
32073
- endpoint: args.endpoint
32203
+ // When the install's own resource group holds multiple projects, an
32204
+ // explicit endpoint disambiguates instead of FOUNDRY_PROJECT_MULTIPLE.
32205
+ // Omitted → single-project auto-discovery within that group.
32206
+ endpoint: args.endpoint,
32207
+ resourceGroup: args.resourceGroup,
32208
+ onScopedOut: (dropped) => {
32209
+ excluded = dropped;
32210
+ }
32074
32211
  });
32075
32212
  return { endpoint: p.endpoint, accountScope: p.accountScope };
32076
32213
  } catch (e) {
@@ -32078,7 +32215,11 @@ async function resolveFoundryEndpointWithWait(args, opts = {}) {
32078
32215
  throw new LocalCliError({
32079
32216
  code: "BOOTSTRAP_UI_MULTIPLE_PROJECTS",
32080
32217
  message: `${e.message} bootstrap ui can't pick one safely (it must not deploy the intake agent into the wrong project).`,
32081
- hint: `Re-run with the throwaway project's endpoint, e.g. 'm8t bootstrap ui --repo-root "$(pwd)" --endpoint https://<account>.services.ai.azure.com/api/projects/m8t'. The installer prints it in 'm8t bootstrap status'.`,
32218
+ hint: [
32219
+ "Re-run naming the project you want:",
32220
+ 'm8t bootstrap ui --repo-root "$(pwd)" --endpoint <projectEndpoint>',
32221
+ "'m8t bootstrap status' prints this install's endpoint (result.foundryEndpoint)."
32222
+ ].join("\n"),
32082
32223
  cause: e
32083
32224
  });
32084
32225
  }
@@ -32088,8 +32229,8 @@ async function resolveFoundryEndpointWithWait(args, opts = {}) {
32088
32229
  if (Date.now() >= deadline) {
32089
32230
  throw new LocalCliError({
32090
32231
  code: "BOOTSTRAP_UI_FOUNDRY_NOT_READY",
32091
- message: "Foundry is not ready yet \u2014 no AI project appeared in your subscription before the timeout.",
32092
- hint: "Check 'm8t bootstrap status --watch'; the install may have stalled in foundry-create.",
32232
+ message: args.resourceGroup ? `Foundry is not ready yet \u2014 no AI project appeared in resource group ${args.resourceGroup} before the timeout.` : "Foundry is not ready yet \u2014 no AI project appeared in your subscription before the timeout.",
32233
+ hint: renderNotReadyHint(args.resourceGroup, excluded),
32093
32234
  cause: e
32094
32235
  });
32095
32236
  }
@@ -32119,7 +32260,7 @@ async function ensureFounderFoundryRole(args) {
32119
32260
  });
32120
32261
  }
32121
32262
  function writeWebEnvLocal(args) {
32122
- const envPath = path39.join(args.repoRoot, "apps", "web", ".env.local");
32263
+ const envPath = path40.join(args.repoRoot, "apps", "web", ".env.local");
32123
32264
  let prior = "";
32124
32265
  if (fs35.existsSync(envPath)) {
32125
32266
  prior = fs35.readFileSync(envPath, "utf8");
@@ -32167,7 +32308,7 @@ function readValidInternalSecret(envText) {
32167
32308
  return isValidInternalSecret(values[0]) ? values[0] : void 0;
32168
32309
  }
32169
32310
  function readWebInternalSecret(repoRoot) {
32170
- const envPath = path39.join(repoRoot, "apps", "web", ".env.local");
32311
+ const envPath = path40.join(repoRoot, "apps", "web", ".env.local");
32171
32312
  let secret;
32172
32313
  try {
32173
32314
  secret = readValidInternalSecret(fs35.readFileSync(envPath, "utf8"));
@@ -32222,17 +32363,17 @@ async function installWebDeps(repoRoot) {
32222
32363
  await runInherit("pnpm", ["install"], repoRoot, "BOOTSTRAP_UI_INSTALL_FAILED");
32223
32364
  }
32224
32365
  function onboardingUiPaths(home = os19.homedir()) {
32225
- const dir = path39.join(home, ".m8t");
32366
+ const dir = path40.join(home, ".m8t");
32226
32367
  return {
32227
- logPath: path39.join(dir, "onboarding-ui.log"),
32228
- pidPath: path39.join(dir, "onboarding-ui.pid")
32368
+ logPath: path40.join(dir, "onboarding-ui.log"),
32369
+ pidPath: path40.join(dir, "onboarding-ui.pid")
32229
32370
  };
32230
32371
  }
32231
32372
  function onboardingRelayPaths(home = os19.homedir()) {
32232
- const dir = path39.join(home, ".m8t");
32373
+ const dir = path40.join(home, ".m8t");
32233
32374
  return {
32234
- logPath: path39.join(dir, "onboarding-relay.log"),
32235
- pidPath: path39.join(dir, "onboarding-relay.pid")
32375
+ logPath: path40.join(dir, "onboarding-relay.log"),
32376
+ pidPath: path40.join(dir, "onboarding-relay.pid")
32236
32377
  };
32237
32378
  }
32238
32379
  function isLocalPortOpen(port) {
@@ -32306,7 +32447,7 @@ async function serveOnboardingUiDetached(args) {
32306
32447
  });
32307
32448
  }
32308
32449
  if (managedPid != null) return { alreadyRunning: true, logPath };
32309
- fs35.mkdirSync(path39.dirname(logPath), { recursive: true });
32450
+ fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
32310
32451
  const fd = fs35.openSync(logPath, "a");
32311
32452
  const child = spawn8("pnpm", ["--filter", "web", "dev"], {
32312
32453
  cwd: args.repoRoot,
@@ -32357,7 +32498,7 @@ async function serveOnboardingRelayDetached(args) {
32357
32498
  });
32358
32499
  }
32359
32500
  if (managedPid != null) return { alreadyRunning: true, logPath };
32360
- fs35.mkdirSync(path39.dirname(logPath), { recursive: true });
32501
+ fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
32361
32502
  const fd = fs35.openSync(logPath, "a");
32362
32503
  const child = spawn8("pnpm", ["--filter", "web", "exec", "tsx", "voice-relay-entry.ts"], {
32363
32504
  cwd: args.repoRoot,
@@ -32775,7 +32916,7 @@ var BootstrapUiCommand = class extends M8tCommand {
32775
32916
  repoRoot = Option55.String("--repo-root");
32776
32917
  port = Option55.String("--port", "3000");
32777
32918
  endpoint = Option55.String("--endpoint", {
32778
- description: "Foundry project endpoint to target \u2014 disambiguates when the subscription has multiple projects."
32919
+ description: "Foundry project endpoint to target \u2014 overrides discovery when this install's resource group holds more than one Foundry project."
32779
32920
  });
32780
32921
  prepOnly = Option55.Boolean("--prep-only", false);
32781
32922
  skipInstall = Option55.Boolean("--skip-install", false);
@@ -32816,7 +32957,7 @@ var BootstrapUiCommand = class extends M8tCommand {
32816
32957
  this.context.stderr.write(` ${colors.dim(m)}
32817
32958
  `);
32818
32959
  };
32819
- if (fs36.existsSync(path40.join(os20.homedir(), ".m8t", "config.yaml"))) {
32960
+ if (fs36.existsSync(path41.join(os20.homedir(), ".m8t", "config.yaml"))) {
32820
32961
  out(colors.error("\u26A0 an existing ~/.m8t/config.yaml will override the onboarding app registration in apps/web \u2014 if Microsoft sign-in fails, move it aside and retry."));
32821
32962
  }
32822
32963
  const credential2 = new DefaultAzureCredential24();
@@ -32827,7 +32968,12 @@ var BootstrapUiCommand = class extends M8tCommand {
32827
32968
  {
32828
32969
  credential: credential2,
32829
32970
  subscriptionId: state.subscriptionId,
32830
- endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0
32971
+ endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0,
32972
+ // Scoped to the resource group this install owns — the state file names
32973
+ // it (and the installer was handed the same one), so there is no
32974
+ // guessing between deployments in a shared subscription. Same rationale
32975
+ // as discoverGateway in bootstrap-finalize.ts.
32976
+ resourceGroup: state.resourceGroup
32831
32977
  },
32832
32978
  { onWait: out }
32833
32979
  );
@@ -33020,7 +33166,7 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
33020
33166
  // src/commands/telemetry/enroll.ts
33021
33167
  import * as fs37 from "fs";
33022
33168
  import * as os21 from "os";
33023
- import * as path41 from "path";
33169
+ import * as path42 from "path";
33024
33170
  import { Command as Command60, Option as Option57 } from "clipanion";
33025
33171
  init_errors();
33026
33172
 
@@ -33148,8 +33294,8 @@ var TelemetryEnrollCommand = class extends M8tCommand {
33148
33294
  ...company ? { company } : {},
33149
33295
  ...contactEmail ? { contactEmail } : {}
33150
33296
  });
33151
- const keyDir = fs37.mkdtempSync(path41.join(os21.tmpdir(), "m8t-ingest-key-"));
33152
- const keyFile = path41.join(keyDir, "key");
33297
+ const keyDir = fs37.mkdtempSync(path42.join(os21.tmpdir(), "m8t-ingest-key-"));
33298
+ const keyFile = path42.join(keyDir, "key");
33153
33299
  try {
33154
33300
  fs37.writeFileSync(keyFile, ingestKey, { mode: 384 });
33155
33301
  await runAz(["keyvault", "secret", "set", "--vault-name", kvName, "--name", INGEST_KEY_SECRET, "--file", keyFile, "--only-show-errors"]);