@m8t-stack/cli 0.2.71 → 0.2.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +1371 -846
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1370,7 +1370,7 @@ var init_enable_hosted_brain = __esm({
1370
1370
  import { Builtins, Cli } from "clipanion";
1371
1371
 
1372
1372
  // src/lib/package-version.ts
1373
- var CLI_VERSION = "0.2.71";
1373
+ var CLI_VERSION = "0.2.72";
1374
1374
 
1375
1375
  // src/lib/render-error.ts
1376
1376
  init_errors();
@@ -1917,7 +1917,7 @@ var safeJSON = (text) => {
1917
1917
  };
1918
1918
 
1919
1919
  // ../../node_modules/.pnpm/openai@6.49.0_ws@8.21.1_zod@4.4.3/node_modules/openai/internal/utils/sleep.mjs
1920
- var sleep = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
1920
+ var sleep = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
1921
1921
 
1922
1922
  // ../../node_modules/.pnpm/openai@6.49.0_ws@8.21.1_zod@4.4.3/node_modules/openai/version.mjs
1923
1923
  var VERSION = "6.49.0";
@@ -3028,8 +3028,8 @@ function addRequestID(value, response) {
3028
3028
  var _APIPromise_client;
3029
3029
  var APIPromise = class _APIPromise extends Promise {
3030
3030
  constructor(client, responsePromise, parseResponse2 = defaultParseResponse) {
3031
- super((resolve4) => {
3032
- resolve4(null);
3031
+ super((resolve6) => {
3032
+ resolve6(null);
3033
3033
  });
3034
3034
  this.responsePromise = responsePromise;
3035
3035
  this.parseResponse = parseResponse2;
@@ -3704,12 +3704,12 @@ function encodeURIPath(str4) {
3704
3704
  return str4.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
3705
3705
  }
3706
3706
  var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
3707
- var createPathTagFunction = (pathEncoder = encodeURIPath) => function path43(statics, ...params) {
3707
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path48(statics, ...params) {
3708
3708
  if (statics.length === 1)
3709
3709
  return statics[0];
3710
3710
  let postPath = false;
3711
3711
  const invalidSegments = [];
3712
- const path44 = statics.reduce((previousValue, currentValue, index) => {
3712
+ const path49 = statics.reduce((previousValue, currentValue, index) => {
3713
3713
  if (/[?#]/.test(currentValue)) {
3714
3714
  postPath = true;
3715
3715
  }
@@ -3726,7 +3726,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path43(sta
3726
3726
  }
3727
3727
  return previousValue + currentValue + (index === params.length ? "" : encoded);
3728
3728
  }, "");
3729
- const pathOnly = path44.split(/[?#]/, 1)[0];
3729
+ const pathOnly = path49.split(/[?#]/, 1)[0];
3730
3730
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
3731
3731
  let match;
3732
3732
  while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -3747,10 +3747,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path43(sta
3747
3747
  }, "");
3748
3748
  throw new OpenAIError(`Path parameters result in path with invalid segments:
3749
3749
  ${invalidSegments.map((e) => e.error).join("\n")}
3750
- ${path44}
3750
+ ${path49}
3751
3751
  ${underline}`);
3752
3752
  }
3753
- return path44;
3753
+ return path49;
3754
3754
  };
3755
3755
  var path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
3756
3756
 
@@ -3926,12 +3926,12 @@ var EventStream = class {
3926
3926
  _EventStream_errored.set(this, false);
3927
3927
  _EventStream_aborted.set(this, false);
3928
3928
  _EventStream_catchingPromiseCreated.set(this, false);
3929
- __classPrivateFieldSet(this, _EventStream_connectedPromise, new Promise((resolve4, reject) => {
3930
- __classPrivateFieldSet(this, _EventStream_resolveConnectedPromise, resolve4, "f");
3929
+ __classPrivateFieldSet(this, _EventStream_connectedPromise, new Promise((resolve6, reject) => {
3930
+ __classPrivateFieldSet(this, _EventStream_resolveConnectedPromise, resolve6, "f");
3931
3931
  __classPrivateFieldSet(this, _EventStream_rejectConnectedPromise, reject, "f");
3932
3932
  }), "f");
3933
- __classPrivateFieldSet(this, _EventStream_endPromise, new Promise((resolve4, reject) => {
3934
- __classPrivateFieldSet(this, _EventStream_resolveEndPromise, resolve4, "f");
3933
+ __classPrivateFieldSet(this, _EventStream_endPromise, new Promise((resolve6, reject) => {
3934
+ __classPrivateFieldSet(this, _EventStream_resolveEndPromise, resolve6, "f");
3935
3935
  __classPrivateFieldSet(this, _EventStream_rejectEndPromise, reject, "f");
3936
3936
  }), "f");
3937
3937
  __classPrivateFieldGet(this, _EventStream_connectedPromise, "f").catch(() => {
@@ -4031,11 +4031,11 @@ var EventStream = class {
4031
4031
  * const message = await stream.emitted('message') // rejects if the stream errors
4032
4032
  */
4033
4033
  emitted(event) {
4034
- return new Promise((resolve4, reject) => {
4034
+ return new Promise((resolve6, reject) => {
4035
4035
  __classPrivateFieldSet(this, _EventStream_catchingPromiseCreated, true, "f");
4036
4036
  if (event !== "error")
4037
4037
  this.once("error", reject);
4038
- this.once(event, resolve4);
4038
+ this.once(event, resolve6);
4039
4039
  });
4040
4040
  }
4041
4041
  /**
@@ -4118,8 +4118,8 @@ var EventStream = class {
4118
4118
  }
4119
4119
  if (ended)
4120
4120
  return Promise.resolve(doneResult());
4121
- return new Promise((resolve4, reject) => {
4122
- readQueue.push({ resolve: resolve4, reject });
4121
+ return new Promise((resolve6, reject) => {
4122
+ readQueue.push({ resolve: resolve6, reject });
4123
4123
  });
4124
4124
  },
4125
4125
  return: () => {
@@ -5210,7 +5210,7 @@ var ChatCompletionStream = class _ChatCompletionStream extends AbstractChatCompl
5210
5210
  if (done) {
5211
5211
  return { value: void 0, done: true };
5212
5212
  }
5213
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
5213
+ return new Promise((resolve6, reject) => readQueue.push({ resolve: resolve6, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
5214
5214
  }
5215
5215
  const chunk = pushQueue.shift();
5216
5216
  return { value: chunk, done: false };
@@ -5392,7 +5392,7 @@ var ChatCompletionStreamingRunner = class _ChatCompletionStreamingRunner extends
5392
5392
  if (done) {
5393
5393
  return { value: void 0, done: true };
5394
5394
  }
5395
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
5395
+ return new Promise((resolve6, reject) => readQueue.push({ resolve: resolve6, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
5396
5396
  }
5397
5397
  const event = pushQueue.shift();
5398
5398
  if (!event) {
@@ -8674,7 +8674,7 @@ var AssistantStream = class extends EventStream {
8674
8674
  if (done) {
8675
8675
  return { value: void 0, done: true };
8676
8676
  }
8677
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
8677
+ return new Promise((resolve6, reject) => readQueue.push({ resolve: resolve6, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
8678
8678
  }
8679
8679
  const chunk = pushQueue.shift();
8680
8680
  return { value: chunk, done: false };
@@ -11051,7 +11051,7 @@ var ResponseStream = class _ResponseStream extends EventStream {
11051
11051
  if (done) {
11052
11052
  return { value: void 0, done: true };
11053
11053
  }
11054
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
11054
+ return new Promise((resolve6, reject) => readQueue.push({ resolve: resolve6, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
11055
11055
  }
11056
11056
  const event = pushQueue.shift();
11057
11057
  return { value: event, done: false };
@@ -12201,9 +12201,9 @@ var OpenAI = class {
12201
12201
  this.apiKey = token;
12202
12202
  return true;
12203
12203
  }
12204
- buildURL(path43, query, defaultBaseURL) {
12204
+ buildURL(path48, query, defaultBaseURL) {
12205
12205
  const baseURL = !__classPrivateFieldGet(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
12206
- const url = isAbsoluteURL(path43) ? new URL(path43) : new URL(baseURL + (baseURL.endsWith("/") && path43.startsWith("/") ? path43.slice(1) : path43));
12206
+ const url = isAbsoluteURL(path48) ? new URL(path48) : new URL(baseURL + (baseURL.endsWith("/") && path48.startsWith("/") ? path48.slice(1) : path48));
12207
12207
  const defaultQuery = this.defaultQuery();
12208
12208
  const pathQuery = Object.fromEntries(url.searchParams);
12209
12209
  if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
@@ -12233,24 +12233,24 @@ var OpenAI = class {
12233
12233
  */
12234
12234
  async prepareRequest(request, { url, options }) {
12235
12235
  }
12236
- get(path43, opts) {
12237
- return this.methodRequest("get", path43, opts);
12236
+ get(path48, opts) {
12237
+ return this.methodRequest("get", path48, opts);
12238
12238
  }
12239
- post(path43, opts) {
12240
- return this.methodRequest("post", path43, opts);
12239
+ post(path48, opts) {
12240
+ return this.methodRequest("post", path48, opts);
12241
12241
  }
12242
- patch(path43, opts) {
12243
- return this.methodRequest("patch", path43, opts);
12242
+ patch(path48, opts) {
12243
+ return this.methodRequest("patch", path48, opts);
12244
12244
  }
12245
- put(path43, opts) {
12246
- return this.methodRequest("put", path43, opts);
12245
+ put(path48, opts) {
12246
+ return this.methodRequest("put", path48, opts);
12247
12247
  }
12248
- delete(path43, opts) {
12249
- return this.methodRequest("delete", path43, opts);
12248
+ delete(path48, opts) {
12249
+ return this.methodRequest("delete", path48, opts);
12250
12250
  }
12251
- methodRequest(method, path43, opts) {
12251
+ methodRequest(method, path48, opts) {
12252
12252
  return this.request(Promise.resolve(opts).then((opts2) => {
12253
- return { method, path: path43, ...opts2 };
12253
+ return { method, path: path48, ...opts2 };
12254
12254
  }));
12255
12255
  }
12256
12256
  request(options, remainingRetries = null) {
@@ -12375,8 +12375,8 @@ var OpenAI = class {
12375
12375
  }));
12376
12376
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
12377
12377
  }
12378
- getAPIList(path43, Page2, opts) {
12379
- return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path43, ...opts2 })) : { method: "get", path: path43, ...opts });
12378
+ getAPIList(path48, Page2, opts) {
12379
+ return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path48, ...opts2 })) : { method: "get", path: path48, ...opts });
12380
12380
  }
12381
12381
  requestAPIList(Page2, options) {
12382
12382
  const request = this.makeRequest(options, null, void 0);
@@ -12470,8 +12470,8 @@ var OpenAI = class {
12470
12470
  }
12471
12471
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
12472
12472
  const options = { ...inputOptions };
12473
- const { method, path: path43, query, defaultBaseURL } = options;
12474
- const url = this.buildURL(path43, query, defaultBaseURL);
12473
+ const { method, path: path48, query, defaultBaseURL } = options;
12474
+ const url = this.buildURL(path48, query, defaultBaseURL);
12475
12475
  if ("timeout" in options)
12476
12476
  validatePositiveInteger("timeout", options.timeout);
12477
12477
  options.timeout = options.timeout ?? this.timeout;
@@ -12839,7 +12839,7 @@ function redactAzArgs(args) {
12839
12839
  return out;
12840
12840
  }
12841
12841
  function runAz(args) {
12842
- return new Promise((resolve4, reject) => {
12842
+ return new Promise((resolve6, reject) => {
12843
12843
  const proc = spawn("az", args, { stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" });
12844
12844
  const out = [];
12845
12845
  const err = [];
@@ -12879,7 +12879,7 @@ function runAz(args) {
12879
12879
  );
12880
12880
  return;
12881
12881
  }
12882
- resolve4(Buffer.concat(out).toString("utf8"));
12882
+ resolve6(Buffer.concat(out).toString("utf8"));
12883
12883
  });
12884
12884
  });
12885
12885
  }
@@ -13473,8 +13473,8 @@ var BindCleanupCommand = class extends M8tCommand {
13473
13473
  colors.error("\u26A0") + ` cleaned ${data.cleaned.length.toString()} binding(s); ${data.failed.length.toString()} failed:
13474
13474
  `
13475
13475
  );
13476
- for (const fail of data.failed) {
13477
- this.context.stderr.write(` - ${fail.bindingId} (${fail.channel}): ${fail.originalMessage}
13476
+ for (const fail2 of data.failed) {
13477
+ this.context.stderr.write(` - ${fail2.bindingId} (${fail2.channel}): ${fail2.originalMessage}
13478
13478
  `);
13479
13479
  }
13480
13480
  this.context.stderr.write(
@@ -13517,10 +13517,10 @@ var BindListCommand = class extends M8tCommand {
13517
13517
  const qs = new URLSearchParams();
13518
13518
  if (this.channel) qs.set("channel", this.channel);
13519
13519
  if (this.status) qs.set("status", this.status);
13520
- const path43 = qs.toString().length > 0 ? `/api/bindings?${qs.toString()}` : "/api/bindings";
13520
+ const path48 = qs.toString().length > 0 ? `/api/bindings?${qs.toString()}` : "/api/bindings";
13521
13521
  const data = await apiCall(
13522
13522
  { gatewayUrl: ctx.gatewayUrl, gatewayClientId: ctx.gatewayClientId },
13523
- { method: "GET", path: path43 },
13523
+ { method: "GET", path: path48 },
13524
13524
  (msg) => this.context.stderr.write(msg + "\n")
13525
13525
  );
13526
13526
  if (mode === "json") {
@@ -14434,13 +14434,13 @@ async function createGitHubApp(args) {
14434
14434
  const setupUrl = `${base}/setup`;
14435
14435
  let createdApp = null;
14436
14436
  let polledInstallationId = null;
14437
- return new Promise((resolve4, reject) => {
14437
+ return new Promise((resolve6, reject) => {
14438
14438
  let settled = false;
14439
14439
  let server;
14440
14440
  const complete = (installationId) => {
14441
14441
  if (settled || !createdApp) return;
14442
14442
  settled = true;
14443
- resolve4({ app: createdApp, installationId });
14443
+ resolve6({ app: createdApp, installationId });
14444
14444
  setTimeout(() => {
14445
14445
  server.close();
14446
14446
  }, 2500);
@@ -14589,7 +14589,7 @@ function outgoingSidecarToPreserve(home, pointerText, sidecarExists) {
14589
14589
  // src/lib/gh-helpers.ts
14590
14590
  init_errors();
14591
14591
  import { spawn as spawn2 } from "child_process";
14592
- var defaultGhExec = (cmd, args) => new Promise((resolve4) => {
14592
+ var defaultGhExec = (cmd, args) => new Promise((resolve6) => {
14593
14593
  const child = spawn2(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
14594
14594
  let stdout = "";
14595
14595
  let stderr = "";
@@ -14597,7 +14597,7 @@ var defaultGhExec = (cmd, args) => new Promise((resolve4) => {
14597
14597
  const done = (r) => {
14598
14598
  if (!settled) {
14599
14599
  settled = true;
14600
- resolve4(r);
14600
+ resolve6(r);
14601
14601
  }
14602
14602
  };
14603
14603
  child.stdout.on("data", (d) => {
@@ -14766,8 +14766,8 @@ ${r.stderr}`;
14766
14766
  message: `gh api /repos/${slug} failed (exit ${r.exitCode.toString()}): ${(r.stderr || r.stdout).slice(0, 200)}`
14767
14767
  });
14768
14768
  },
14769
- getFile: async (path43) => {
14770
- const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path43}`]);
14769
+ getFile: async (path48) => {
14770
+ const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path48}`]);
14771
14771
  return r.exitCode === 0 ? r.stdout : null;
14772
14772
  },
14773
14773
  isEmpty: async () => {
@@ -15049,11 +15049,11 @@ var BrainCheckAppCommand = class extends M8tCommand {
15049
15049
  // src/commands/brain/create.ts
15050
15050
  init_esm2();
15051
15051
  import { Command as Command18, Option as Option17 } from "clipanion";
15052
- import { execFileSync, spawnSync } from "child_process";
15053
- import { readFileSync as readFileSync7 } from "fs";
15054
- import * as fs11 from "fs";
15055
- import * as os4 from "os";
15056
- import * as path11 from "path";
15052
+ import { execFileSync as execFileSync3, spawnSync } from "child_process";
15053
+ import { readFileSync as readFileSync9 } from "fs";
15054
+ import * as fs14 from "fs";
15055
+ import * as os5 from "os";
15056
+ import * as path14 from "path";
15057
15057
  import * as readline2 from "readline/promises";
15058
15058
  import { DefaultAzureCredential as DefaultAzureCredential4 } from "@azure/identity";
15059
15059
  init_errors();
@@ -15556,8 +15556,107 @@ async function createBrainEnabledVersion(args) {
15556
15556
 
15557
15557
  // src/lib/brain-seed.ts
15558
15558
  init_errors();
15559
- import * as fs10 from "fs";
15560
- import * as path10 from "path";
15559
+ import * as fs13 from "fs";
15560
+ import * as path13 from "path";
15561
+
15562
+ // src/lib/agent-content-sync.ts
15563
+ init_errors();
15564
+ import * as fs12 from "fs";
15565
+ import * as path12 from "path";
15566
+ import { execFileSync as execFileSync2 } from "child_process";
15567
+
15568
+ // src/lib/release-pin.ts
15569
+ init_errors();
15570
+ var PIN_SCHEMA_VERSION = 2;
15571
+ var REF_RE = /^[0-9a-f]{40}$/;
15572
+ var DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
15573
+ var REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
15574
+ function fail(source, detail, hint) {
15575
+ throw new LocalCliError({
15576
+ code: "RELEASE_PIN_INVALID",
15577
+ message: `${source}: ${detail}`,
15578
+ ...hint ? { hint } : {}
15579
+ });
15580
+ }
15581
+ function parseAgent(source, key2, raw) {
15582
+ if (typeof raw !== "object" || raw === null) fail(source, `agents.${key2} is not an object.`);
15583
+ const a = raw;
15584
+ if (typeof a.repo !== "string" || !REPO_RE.test(a.repo)) {
15585
+ fail(source, `agents.${key2}.repo must be "owner/name", got ${JSON.stringify(a.repo)}.`);
15586
+ }
15587
+ if (typeof a.ref !== "string" || !REF_RE.test(a.ref)) {
15588
+ fail(
15589
+ source,
15590
+ `agents.${key2}.ref must be a 40-hex commit sha, got ${JSON.stringify(a.ref)}.`,
15591
+ "A tag or branch can move, so it is not a pin. Use `m8t agent-content pin <key>` to resolve one."
15592
+ );
15593
+ }
15594
+ if (a.visibility !== "public" && a.visibility !== "private") {
15595
+ fail(source, `agents.${key2}.visibility must be "public" or "private", got ${JSON.stringify(a.visibility)}.`);
15596
+ }
15597
+ if (typeof a.persona !== "string" || a.persona.length === 0) {
15598
+ fail(source, `agents.${key2}.persona must be a non-empty persona slug.`);
15599
+ }
15600
+ if (typeof a.contentSha !== "string" || !DIGEST_RE.test(a.contentSha)) {
15601
+ fail(source, `agents.${key2}.contentSha must be "sha256:<64-hex>", got ${JSON.stringify(a.contentSha)}.`);
15602
+ }
15603
+ return { repo: a.repo, ref: a.ref, visibility: a.visibility, persona: a.persona, contentSha: a.contentSha };
15604
+ }
15605
+ function parseReleasePin(json, source) {
15606
+ let doc;
15607
+ try {
15608
+ doc = JSON.parse(json);
15609
+ } catch (e) {
15610
+ fail(source, `not valid JSON: ${e.message}`);
15611
+ }
15612
+ if (typeof doc !== "object" || doc === null) fail(source, "top level is not an object.");
15613
+ const d = doc;
15614
+ if (d.schemaVersion !== PIN_SCHEMA_VERSION) {
15615
+ fail(
15616
+ source,
15617
+ `schemaVersion ${JSON.stringify(d.schemaVersion)} is not the expected ${PIN_SCHEMA_VERSION.toString()}.`,
15618
+ "This CLI is older or newer than the pin it is reading. Guessing at an unknown shape is how a stale pin ships as if it were current."
15619
+ );
15620
+ }
15621
+ if (typeof d.platformVersion !== "string") fail(source, "platformVersion is missing.");
15622
+ const rawAgents = d.agents ?? {};
15623
+ if (typeof rawAgents !== "object" || rawAgents === null || Array.isArray(rawAgents)) {
15624
+ fail(source, "agents must be an object keyed by agent name.");
15625
+ }
15626
+ const agents = {};
15627
+ const personaOwner = /* @__PURE__ */ new Map();
15628
+ for (const [key2, raw] of Object.entries(rawAgents)) {
15629
+ const agent = parseAgent(source, key2, raw);
15630
+ const existing = personaOwner.get(agent.persona);
15631
+ if (existing !== void 0) {
15632
+ fail(
15633
+ source,
15634
+ `agents.${existing} and agents.${key2} both claim persona '${agent.persona}'.`,
15635
+ "Two sources for one persona means hydration order decides which wins \u2014 silently."
15636
+ );
15637
+ }
15638
+ personaOwner.set(agent.persona, key2);
15639
+ agents[key2] = agent;
15640
+ }
15641
+ const personas = d.personas ?? [];
15642
+ if (!Array.isArray(personas) || personas.some((p) => typeof p !== "string")) {
15643
+ fail(source, "personas must be an array of strings.");
15644
+ }
15645
+ return {
15646
+ schemaVersion: d.schemaVersion,
15647
+ platformVersion: d.platformVersion,
15648
+ agents,
15649
+ personas
15650
+ };
15651
+ }
15652
+
15653
+ // src/lib/agent-content.ts
15654
+ init_errors();
15655
+ import * as fs11 from "fs";
15656
+ import * as os4 from "os";
15657
+ import * as path11 from "path";
15658
+ import { createHash } from "crypto";
15659
+ import { parse as parseYaml5 } from "yaml";
15561
15660
 
15562
15661
  // src/lib/seed-manifest.ts
15563
15662
  import * as fs9 from "fs";
@@ -15612,22 +15711,322 @@ function deriveOwnedPaths(seedDir) {
15612
15711
  return [...owned].sort((a, b) => a.localeCompare(b));
15613
15712
  }
15614
15713
 
15714
+ // src/lib/tarball-cache.ts
15715
+ init_errors();
15716
+ import * as fs10 from "fs";
15717
+ import * as path10 from "path";
15718
+ import { execFileSync } from "child_process";
15719
+ function extractTarGz(tgz, into) {
15720
+ execFileSync("tar", ["-xzf", tgz, "-C", into, "--strip-components=1"]);
15721
+ }
15722
+ function publishAtomically(args) {
15723
+ try {
15724
+ fs10.renameSync(args.from, args.dest);
15725
+ } catch (e) {
15726
+ const err = e;
15727
+ const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs10.existsSync(path10.join(args.dest, args.sentinel));
15728
+ if (!isBenignRace) {
15729
+ throw new LocalCliError({
15730
+ code: args.errorCode,
15731
+ message: `Could not publish cache to ${args.dest}: ${err.message}`
15732
+ });
15733
+ }
15734
+ }
15735
+ }
15736
+
15737
+ // src/lib/agent-content.ts
15738
+ var AGENT_DIR = "agent";
15739
+ var AGENT_SEED_DIRS = [...SEED_PATHS, "memory"];
15740
+ var AGENT_SEED_FILES = ["NOTICE"];
15741
+ var PERSONA_REL = `${AGENT_DIR}/persona.md`;
15742
+ function walk(base, dir, out) {
15743
+ for (const entry of fs11.readdirSync(dir, { withFileTypes: true })) {
15744
+ const abs = path11.join(dir, entry.name);
15745
+ if (entry.isDirectory()) walk(base, abs, out);
15746
+ else if (entry.isFile()) out.push(path11.relative(base, abs).split(path11.sep).join("/"));
15747
+ }
15748
+ }
15749
+ function collectAgentContent(repoDir) {
15750
+ const personaAbs = path11.join(repoDir, AGENT_DIR, "persona.md");
15751
+ if (!fs11.existsSync(personaAbs)) {
15752
+ throw new LocalCliError({
15753
+ code: "AGENT_CONTENT_INVALID",
15754
+ message: `'${repoDir}' is not an agent repo: no ${PERSONA_REL}.`,
15755
+ hint: "An agent repo declares its agent at agent/persona.md \u2014 see docs/architecture/AGENT-REPO-CONTRACT.md."
15756
+ });
15757
+ }
15758
+ const rels = [];
15759
+ walk(repoDir, path11.join(repoDir, AGENT_DIR), rels);
15760
+ for (const dir of AGENT_SEED_DIRS) {
15761
+ const abs = path11.join(repoDir, dir);
15762
+ if (fs11.existsSync(abs) && fs11.statSync(abs).isDirectory()) walk(repoDir, abs, rels);
15763
+ }
15764
+ for (const file of AGENT_SEED_FILES) {
15765
+ const abs = path11.join(repoDir, file);
15766
+ if (fs11.existsSync(abs) && fs11.statSync(abs).isFile()) rels.push(file);
15767
+ }
15768
+ const files = /* @__PURE__ */ new Map();
15769
+ for (const rel of rels) files.set(rel, fs11.readFileSync(path11.join(repoDir, rel)));
15770
+ return { files };
15771
+ }
15772
+ function digestAgentContent(content) {
15773
+ const records = [...content.files.entries()].map(([rel, bytes]) => [rel.split("\\").join("/"), createHash("sha256").update(bytes).digest("hex")]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0).map(([rel, sha]) => `${sha} ${rel}`);
15774
+ return "sha256:" + createHash("sha256").update(records.join("\0")).digest("hex");
15775
+ }
15776
+ function readDeclaredPersona(content) {
15777
+ const raw = content.files.get(PERSONA_REL);
15778
+ if (!raw) {
15779
+ throw new LocalCliError({
15780
+ code: "AGENT_CONTENT_INVALID",
15781
+ message: `Agent content carries no ${PERSONA_REL}.`
15782
+ });
15783
+ }
15784
+ const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw.toString("utf8"));
15785
+ const name = fm ? parseYaml5(fm[1])?.name : void 0;
15786
+ if (typeof name !== "string" || name.length === 0) {
15787
+ throw new LocalCliError({
15788
+ code: "AGENT_CONTENT_INVALID",
15789
+ message: `${PERSONA_REL} declares no frontmatter 'name'.`,
15790
+ hint: "Layer 1 of the persona schema requires `name` \u2014 see docs/architecture/SCHEMA.md."
15791
+ });
15792
+ }
15793
+ return name;
15794
+ }
15795
+ function hydrateAgentContent(content, destRoot, persona) {
15796
+ const personaDir = path11.join(destRoot, "personas", persona);
15797
+ const seedDir = path11.join(destRoot, "brain-seeds", persona);
15798
+ fs11.mkdirSync(destRoot, { recursive: true });
15799
+ const stage = fs11.mkdtempSync(path11.join(destRoot, `.hydrate-${persona}-`));
15800
+ try {
15801
+ for (const [rel, bytes] of content.files) {
15802
+ const dest = rel.startsWith(`${AGENT_DIR}/`) ? path11.join(stage, "personas", rel.slice(AGENT_DIR.length + 1)) : path11.join(stage, "seed", rel);
15803
+ fs11.mkdirSync(path11.dirname(dest), { recursive: true });
15804
+ fs11.writeFileSync(dest, bytes);
15805
+ }
15806
+ swapInto(path11.join(stage, "personas"), personaDir);
15807
+ swapInto(path11.join(stage, "seed"), seedDir);
15808
+ } finally {
15809
+ fs11.rmSync(stage, { recursive: true, force: true });
15810
+ }
15811
+ }
15812
+ function swapInto(from, dest) {
15813
+ if (!fs11.existsSync(from)) {
15814
+ fs11.rmSync(dest, { recursive: true, force: true });
15815
+ return;
15816
+ }
15817
+ fs11.mkdirSync(path11.dirname(dest), { recursive: true });
15818
+ const old = `${dest}.old-${process.pid.toString()}`;
15819
+ fs11.rmSync(old, { recursive: true, force: true });
15820
+ if (fs11.existsSync(dest)) fs11.renameSync(dest, old);
15821
+ fs11.renameSync(from, dest);
15822
+ fs11.rmSync(old, { recursive: true, force: true });
15823
+ }
15824
+ async function resolveToken(deps) {
15825
+ const env = deps.env ?? process.env;
15826
+ const fromEnv = [env.AGENT_CONTENT_TOKEN, env.GH_TOKEN, env.GITHUB_TOKEN].find((t) => t);
15827
+ if (fromEnv) return fromEnv;
15828
+ try {
15829
+ const tok = await (deps.ghToken ?? getGhToken)();
15830
+ return tok || void 0;
15831
+ } catch {
15832
+ return void 0;
15833
+ }
15834
+ }
15835
+ function assertMatchesPin(content, pin) {
15836
+ const actual = digestAgentContent(content);
15837
+ if (actual !== pin.contentSha) {
15838
+ throw new LocalCliError({
15839
+ code: "AGENT_CONTENT_DIGEST_MISMATCH",
15840
+ message: `${pin.repo}@${pin.ref}: content digest ${actual} does not match the pinned ${pin.contentSha}.`,
15841
+ hint: "The pin and the ref disagree. Re-derive with `m8t agent-content pin <key>`, or point the pin at the right commit."
15842
+ });
15843
+ }
15844
+ const declared = readDeclaredPersona(content);
15845
+ if (declared !== pin.persona) {
15846
+ throw new LocalCliError({
15847
+ code: "AGENT_CONTENT_PERSONA_MISMATCH",
15848
+ message: `${pin.repo}@${pin.ref} declares persona '${declared}', but the pin expects '${pin.persona}'.`,
15849
+ hint: "Align the pin's `persona` with the frontmatter `name` in the repo's agent/persona.md."
15850
+ });
15851
+ }
15852
+ }
15853
+ async function downloadAgentRepo(pin, tmpDir, deps) {
15854
+ const token = await resolveToken(deps);
15855
+ if (pin.visibility === "private" && !token) {
15856
+ throw new LocalCliError({
15857
+ code: "AGENT_CONTENT_TOKEN_MISSING",
15858
+ message: `${pin.repo} is a private agent repo and no read token is available.`,
15859
+ hint: "Set AGENT_CONTENT_TOKEN (contents:read on that repo), or GH_TOKEN / GITHUB_TOKEN, or run `gh auth login`."
15860
+ });
15861
+ }
15862
+ const url = `https://api.github.com/repos/${pin.repo}/tarball/${pin.ref}`;
15863
+ const res = await (deps.fetchImpl ?? fetch)(url, {
15864
+ headers: token ? { Authorization: `Bearer ${token}` } : {}
15865
+ });
15866
+ if (!res.ok) {
15867
+ const status = res.status.toString();
15868
+ throw new LocalCliError({
15869
+ code: "AGENT_CONTENT_FETCH_FAILED",
15870
+ message: `GET ${url} \u2192 HTTP ${status} (agent '${pin.repo}' at ref ${pin.ref}).`,
15871
+ hint: res.status === 404 && pin.visibility === "private" ? "A 404 on a private repo usually means the token lacks access, not that the ref is wrong. Check AGENT_CONTENT_TOKEN's permission on that repo." : res.status === 404 ? "Check that the pinned ref exists on that repo." : "Transient GitHub failures are retryable; a persistent one is not."
15872
+ });
15873
+ }
15874
+ const tgz = path11.join(tmpDir, "src.tar.gz");
15875
+ fs11.writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
15876
+ const unpacked = path11.join(tmpDir, "unpacked");
15877
+ fs11.mkdirSync(unpacked);
15878
+ extractTarGz(tgz, unpacked);
15879
+ return unpacked;
15880
+ }
15881
+ async function resolveAgentContent(key2, pin, deps = {}) {
15882
+ const cacheRoot = deps.cacheRoot ?? path11.join(os4.homedir(), ".m8t", "cache");
15883
+ const digestTag = pin.contentSha.replace(/^sha256:/, "").slice(0, 16);
15884
+ const dest = path11.join(cacheRoot, `agent-${key2}-${digestTag}`);
15885
+ if (fs11.existsSync(path11.join(dest, PERSONA_REL))) {
15886
+ try {
15887
+ const cached = collectAgentContent(dest);
15888
+ assertMatchesPin(cached, pin);
15889
+ return cached;
15890
+ } catch {
15891
+ deps.onNotice?.(
15892
+ `agent content cache for '${key2}' failed verification \u2014 discarding ${dest} and re-fetching.`
15893
+ );
15894
+ fs11.rmSync(dest, { recursive: true, force: true });
15895
+ }
15896
+ }
15897
+ fs11.mkdirSync(cacheRoot, { recursive: true });
15898
+ fs11.rmSync(dest, { recursive: true, force: true });
15899
+ const tmpDir = fs11.mkdtempSync(path11.join(cacheRoot, `.dl-${key2}-`));
15900
+ try {
15901
+ const unpacked = await downloadAgentRepo(pin, tmpDir, deps);
15902
+ const content = collectAgentContent(unpacked);
15903
+ assertMatchesPin(content, pin);
15904
+ publishAtomically({
15905
+ from: unpacked,
15906
+ dest,
15907
+ sentinel: PERSONA_REL,
15908
+ errorCode: "AGENT_CONTENT_CACHE_PUBLISH_FAILED"
15909
+ });
15910
+ return content;
15911
+ } finally {
15912
+ fs11.rmSync(tmpDir, { recursive: true, force: true });
15913
+ }
15914
+ }
15915
+ async function fetchAgentContentForPinning(source, deps = {}) {
15916
+ const tmpDir = fs11.mkdtempSync(path11.join(os4.tmpdir(), "m8t-agent-pin-"));
15917
+ try {
15918
+ return collectAgentContent(await downloadAgentRepo(source, tmpDir, deps));
15919
+ } finally {
15920
+ fs11.rmSync(tmpDir, { recursive: true, force: true });
15921
+ }
15922
+ }
15923
+ function collectHydratedContent(destRoot, pin) {
15924
+ const personaDir = path11.join(destRoot, "personas", pin.persona);
15925
+ const seedDir = path11.join(destRoot, "brain-seeds", pin.persona);
15926
+ if (!fs11.existsSync(path11.join(personaDir, "persona.md"))) return null;
15927
+ const files = /* @__PURE__ */ new Map();
15928
+ const rels = [];
15929
+ walk(personaDir, personaDir, rels);
15930
+ for (const rel of rels) files.set(`${AGENT_DIR}/${rel}`, fs11.readFileSync(path11.join(personaDir, rel)));
15931
+ if (fs11.existsSync(seedDir)) {
15932
+ const seedRels = [];
15933
+ walk(seedDir, seedDir, seedRels);
15934
+ for (const rel of seedRels) files.set(rel, fs11.readFileSync(path11.join(seedDir, rel)));
15935
+ }
15936
+ const content = { files };
15937
+ return digestAgentContent(content) === pin.contentSha ? content : null;
15938
+ }
15939
+ async function hydrateAgentsInto(destRoot, agents, deps = {}) {
15940
+ const resolved = [];
15941
+ for (const [key2, pin] of Object.entries(agents)) {
15942
+ if (collectHydratedContent(destRoot, pin)) continue;
15943
+ resolved.push({ pin, content: await resolveAgentContent(key2, pin, deps) });
15944
+ }
15945
+ for (const { pin, content } of resolved) hydrateAgentContent(content, destRoot, pin.persona);
15946
+ }
15947
+
15948
+ // src/lib/agent-content-sync.ts
15949
+ var PIN_REL_PATH = "installer/release-pin.json";
15950
+ async function syncAgentContent(args) {
15951
+ const pinPath = path12.join(args.root, PIN_REL_PATH);
15952
+ if (!fs12.existsSync(pinPath)) {
15953
+ throw new LocalCliError({
15954
+ code: "RELEASE_PIN_MISSING",
15955
+ message: `No ${PIN_REL_PATH} under '${args.root}'.`,
15956
+ hint: "Run from an m8t checkout, or pass --root pointing at one."
15957
+ });
15958
+ }
15959
+ const pin = parseReleasePin(fs12.readFileSync(pinPath, "utf8"), pinPath);
15960
+ await hydrateAgentsInto(args.root, pin.agents, args.deps);
15961
+ return Object.values(pin.agents).map((a) => ({ persona: a.persona, repo: a.repo, ref: a.ref }));
15962
+ }
15963
+ function agentContentHint(root, persona) {
15964
+ try {
15965
+ const pin = parseReleasePin(fs12.readFileSync(path12.join(root, PIN_REL_PATH), "utf8"), PIN_REL_PATH);
15966
+ const agent = Object.values(pin.agents).find((a) => a.persona === persona);
15967
+ if (!agent) return void 0;
15968
+ return `'${persona}' lives in ${agent.repo}, not in this repo \u2014 its content is generated, not committed. Run \`pnpm agent-content:sync\` to materialize it.`;
15969
+ } catch {
15970
+ return void 0;
15971
+ }
15972
+ }
15973
+ function resolveRemoteRef(repo, branch) {
15974
+ let out;
15975
+ try {
15976
+ out = execFileSync2("git", ["ls-remote", `https://github.com/${repo}.git`, branch], {
15977
+ encoding: "utf8",
15978
+ stdio: ["ignore", "pipe", "pipe"]
15979
+ });
15980
+ } catch (e) {
15981
+ throw new LocalCliError({
15982
+ code: "AGENT_REF_RESOLVE_FAILED",
15983
+ message: `Could not resolve ${repo}#${branch}: ${e.message}`,
15984
+ hint: "Check the repo name, the branch, and that your git can read it (`gh auth setup-git` for private repos)."
15985
+ });
15986
+ }
15987
+ const sha = /^([0-9a-f]{40})\s/.exec(out.trim())?.[1];
15988
+ if (!sha) {
15989
+ throw new LocalCliError({
15990
+ code: "AGENT_REF_RESOLVE_FAILED",
15991
+ message: `${repo} has no branch '${branch}'.`
15992
+ });
15993
+ }
15994
+ return sha;
15995
+ }
15996
+ async function derivePin(args) {
15997
+ const ref = (args.resolveRef ?? resolveRemoteRef)(args.current.repo, args.branch);
15998
+ const content = await fetchAgentContentForPinning(
15999
+ { repo: args.current.repo, ref, visibility: args.current.visibility },
16000
+ args.deps
16001
+ );
16002
+ return {
16003
+ ...args.current,
16004
+ ref,
16005
+ persona: readDeclaredPersona(content),
16006
+ contentSha: digestAgentContent(content)
16007
+ };
16008
+ }
16009
+
15615
16010
  // src/lib/brain-seed.ts
15616
16011
  function resolveSeed(name) {
15617
- const dir = path10.join(resolveRepoRoot(), "brain-seeds", name);
15618
- if (!fs10.existsSync(dir)) {
16012
+ const root = resolveRepoRoot();
16013
+ const dir = path13.join(root, "brain-seeds", name);
16014
+ if (!fs13.existsSync(dir)) {
15619
16015
  throw new LocalCliError({
15620
16016
  code: "SEED_NOT_FOUND",
15621
16017
  message: `--seed "${name}": no brain-seeds/${name}/ directory found.`,
15622
- hint: "Seeds live under brain-seeds/. Check the name, or omit --seed for an unseeded brain."
16018
+ // A product agent's seed is generated from its pinned repo rather than
16019
+ // committed here, so "check the name" is the wrong advice for the most
16020
+ // likely cause — an un-hydrated checkout.
16021
+ hint: agentContentHint(root, name) ?? "Seeds live under brain-seeds/. Check the name, or omit --seed for an unseeded brain."
15623
16022
  });
15624
16023
  }
15625
16024
  return dir;
15626
16025
  }
15627
16026
  function materializeBrainTree(opts) {
15628
- fs10.cpSync(opts.templateSrc, opts.destDir, { recursive: true });
16027
+ fs13.cpSync(opts.templateSrc, opts.destDir, { recursive: true });
15629
16028
  if (opts.seedDir) {
15630
- fs10.cpSync(opts.seedDir, opts.destDir, { recursive: true });
16029
+ fs13.cpSync(opts.seedDir, opts.destDir, { recursive: true });
15631
16030
  }
15632
16031
  }
15633
16032
  function writeSeedMarker(args) {
@@ -15637,21 +16036,21 @@ function writeSeedMarker(args) {
15637
16036
  refreshedToVersion: args.version,
15638
16037
  ownedPaths: deriveOwnedPaths(args.seedDir)
15639
16038
  }]);
15640
- const dest = path10.join(args.destDir, SEED_MANIFEST_PATH);
15641
- fs10.mkdirSync(path10.dirname(dest), { recursive: true });
15642
- fs10.writeFileSync(dest, serializeSeedManifest(manifest));
16039
+ const dest = path13.join(args.destDir, SEED_MANIFEST_PATH);
16040
+ fs13.mkdirSync(path13.dirname(dest), { recursive: true });
16041
+ fs13.writeFileSync(dest, serializeSeedManifest(manifest));
15643
16042
  }
15644
16043
 
15645
16044
  // src/lib/github-app-repo.ts
15646
16045
  init_errors();
15647
16046
  init_esm2();
15648
16047
  import { spawn as spawn3 } from "child_process";
15649
- import { parse as parseYaml5 } from "yaml";
16048
+ import { parse as parseYaml6 } from "yaml";
15650
16049
  function isM8tBrainMarker(yamlText) {
15651
16050
  if (!yamlText.trim()) return false;
15652
16051
  let parsed;
15653
16052
  try {
15654
- parsed = parseYaml5(yamlText);
16053
+ parsed = parseYaml6(yamlText);
15655
16054
  } catch {
15656
16055
  return false;
15657
16056
  }
@@ -15683,7 +16082,7 @@ async function createBlankRepo(args) {
15683
16082
  return { cloneUrl: j.clone_url, defaultBranch: j.default_branch ?? "main" };
15684
16083
  }
15685
16084
  function run(cmd, cmdArgs, cwd, env) {
15686
- return new Promise((resolve4, reject) => {
16085
+ return new Promise((resolve6, reject) => {
15687
16086
  const c = spawn3(cmd, cmdArgs, { cwd, env: { ...process.env, ...env }, stdio: ["ignore", "pipe", "pipe"] });
15688
16087
  let err = "";
15689
16088
  c.stderr.on("data", (d) => {
@@ -15699,7 +16098,7 @@ function run(cmd, cmdArgs, cwd, env) {
15699
16098
  });
15700
16099
  c.on("close", (code) => {
15701
16100
  if (code === 0) {
15702
- resolve4();
16101
+ resolve6();
15703
16102
  } else {
15704
16103
  reject(
15705
16104
  new LocalCliError({
@@ -15883,7 +16282,7 @@ function appRepoProbe(args) {
15883
16282
  const res = await doFetch(`${GH_API}/repos/${args.repo}`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
15884
16283
  return res.status;
15885
16284
  },
15886
- getFile: (path43) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path43, fetchImpl: args.fetchImpl }),
16285
+ getFile: (path48) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path48, fetchImpl: args.fetchImpl }),
15887
16286
  isEmpty: async () => {
15888
16287
  const res = await doFetch(`${GH_API}/repos/${args.repo}/contents`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
15889
16288
  return res.status === 404;
@@ -16097,7 +16496,7 @@ function resolveScaffoldCommit(repoRoot, env) {
16097
16496
  const baked = env.M8T_BUILD_SHA?.trim();
16098
16497
  if (baked) return baked;
16099
16498
  try {
16100
- return execFileSync("git", ["rev-parse", "HEAD"], {
16499
+ return execFileSync3("git", ["rev-parse", "HEAD"], {
16101
16500
  cwd: repoRoot,
16102
16501
  encoding: "utf8",
16103
16502
  stdio: ["ignore", "pipe", "ignore"]
@@ -16180,7 +16579,7 @@ var BrainCreateCommand = class extends M8tCommand {
16180
16579
  if (useAppPath) {
16181
16580
  await assertInstallationPermissions({
16182
16581
  appId: appIdOpt,
16183
- privateKeyPem: readFileSync7(appPemOpt, "utf8"),
16582
+ privateKeyPem: readFileSync9(appPemOpt, "utf8"),
16184
16583
  installationId: installationIdOpt,
16185
16584
  org: owner,
16186
16585
  onUnverified: (m) => this.context.stderr.write(` ${colors.dim(`warning: ${m}`)}
@@ -16212,15 +16611,15 @@ var BrainCreateCommand = class extends M8tCommand {
16212
16611
  agentEndpoint
16213
16612
  });
16214
16613
  const repoRoot = resolveRepoRoot();
16215
- const templateSrc = path11.join(repoRoot, "brain-template");
16216
- if (!fs11.existsSync(templateSrc)) {
16614
+ const templateSrc = path14.join(repoRoot, "brain-template");
16615
+ if (!fs14.existsSync(templateSrc)) {
16217
16616
  throw new LocalCliError({
16218
16617
  code: "TEMPLATE_MISSING",
16219
16618
  message: `brain-template/ missing at ${templateSrc}`,
16220
16619
  hint: "Ensure brain-template/ exists at the repo root (same level as apps/)."
16221
16620
  });
16222
16621
  }
16223
- const tmpDir = fs11.mkdtempSync(path11.join(os4.tmpdir(), `m8t-brain-create-${worker}-`));
16622
+ const tmpDir = fs14.mkdtempSync(path14.join(os5.tmpdir(), `m8t-brain-create-${worker}-`));
16224
16623
  let result2;
16225
16624
  let resolvedInstallationId = null;
16226
16625
  const force = this.reuse === true ? "reuse" : this.newName === true ? "new" : void 0;
@@ -16230,7 +16629,7 @@ var BrainCreateCommand = class extends M8tCommand {
16230
16629
  if (useAppPath) {
16231
16630
  token = await mintInstallationTokenFromPem({
16232
16631
  appId: appIdOpt,
16233
- privateKeyPem: readFileSync7(appPemOpt, "utf8"),
16632
+ privateKeyPem: readFileSync9(appPemOpt, "utf8"),
16234
16633
  installationId: installationIdOpt
16235
16634
  });
16236
16635
  const tok = token;
@@ -16352,7 +16751,7 @@ var BrainCreateCommand = class extends M8tCommand {
16352
16751
  project
16353
16752
  });
16354
16753
  } finally {
16355
- fs11.rmSync(tmpDir, { recursive: true, force: true });
16754
+ fs14.rmSync(tmpDir, { recursive: true, force: true });
16356
16755
  }
16357
16756
  if (mode === "json") {
16358
16757
  this.context.stdout.write(
@@ -16804,9 +17203,9 @@ init_errors();
16804
17203
  // src/lib/brain-unlink.ts
16805
17204
  init_esm2();
16806
17205
  init_errors();
16807
- import * as fs12 from "fs";
16808
- import * as os5 from "os";
16809
- import * as path12 from "path";
17206
+ import * as fs15 from "fs";
17207
+ import * as os6 from "os";
17208
+ import * as path15 from "path";
16810
17209
  init_foundry_agent_get();
16811
17210
  init_foundry_agent_version();
16812
17211
  var FOUNDRY_ARM_API2 = "2025-04-01-preview";
@@ -16837,15 +17236,15 @@ async function unlinkBrain(args) {
16837
17236
  if (yaml?.personaPath) {
16838
17237
  let personaPath = yaml.personaPath;
16839
17238
  if (!personaPath.startsWith("/")) {
16840
- const marker = path12.join(args.home ?? os5.homedir(), ".m8t", "repo-root");
16841
- if (!fs12.existsSync(marker)) {
17239
+ const marker = path15.join(args.home ?? os6.homedir(), ".m8t", "repo-root");
17240
+ if (!fs15.existsSync(marker)) {
16842
17241
  throw new LocalCliError({
16843
17242
  code: "PERSONA_PATH_NOT_ABSOLUTE",
16844
17243
  message: `personaPath '${personaPath}' is relative and the repo-root marker is missing.`,
16845
17244
  hint: "Re-run 'm8t install' from a fresh m8t checkout (writes ~/.m8t/repo-root) \u2014 or edit the personaPath to absolute."
16846
17245
  });
16847
17246
  }
16848
- personaPath = path12.join(fs12.readFileSync(marker, "utf8").trim(), personaPath);
17247
+ personaPath = path15.join(fs15.readFileSync(marker, "utf8").trim(), personaPath);
16849
17248
  }
16850
17249
  strippedInstructions = renderPersonaBody(personaPath, yaml.fillableFieldValues ?? {}, args.agentName);
16851
17250
  } else {
@@ -17066,38 +17465,41 @@ import { DefaultAzureCredential as DefaultAzureCredential9 } from "@azure/identi
17066
17465
  init_errors();
17067
17466
 
17068
17467
  // src/lib/deploy-prompt-advisor.ts
17069
- import * as fs13 from "fs";
17070
- import * as path13 from "path";
17071
- import { parse as parseYaml6 } from "yaml";
17468
+ import * as fs16 from "fs";
17469
+ import * as path16 from "path";
17470
+ import { parse as parseYaml7 } from "yaml";
17072
17471
  init_foundry_agents();
17073
17472
  init_errors();
17074
17473
  init_esm();
17075
17474
  function findPersonasRoot(hint) {
17076
- let dir = path13.resolve(hint);
17077
- const fsRoot = path13.parse(dir).root;
17475
+ let dir = path16.resolve(hint);
17476
+ const fsRoot = path16.parse(dir).root;
17078
17477
  for (; ; ) {
17079
- if (fs13.existsSync(path13.join(dir, "personas"))) return dir;
17080
- const parent = path13.dirname(dir);
17478
+ if (fs16.existsSync(path16.join(dir, "personas"))) return dir;
17479
+ const parent = path16.dirname(dir);
17081
17480
  if (parent === dir || dir === fsRoot) return null;
17082
17481
  dir = parent;
17083
17482
  }
17084
17483
  }
17085
17484
  async function deployPromptAdvisor(args) {
17086
17485
  const resolvedRoot = findPersonasRoot(args.repoRoot);
17087
- const personaPath = resolvedRoot ? path13.join(resolvedRoot, "personas", args.persona, "persona.md") : path13.join(args.repoRoot, "personas", args.persona, "persona.md");
17486
+ const personaPath = resolvedRoot ? path16.join(resolvedRoot, "personas", args.persona, "persona.md") : path16.join(args.repoRoot, "personas", args.persona, "persona.md");
17088
17487
  let raw;
17089
17488
  try {
17090
- raw = fs13.readFileSync(personaPath, "utf8");
17489
+ raw = fs16.readFileSync(personaPath, "utf8");
17091
17490
  } catch (e) {
17092
17491
  throw new LocalCliError({
17093
17492
  code: "ADVISOR_PERSONA_MISSING",
17094
17493
  message: `Could not read the persona at '${personaPath}'.`,
17095
- hint: "Run from your m8t repo checkout, or pass --repo-root.",
17494
+ // A product agent's persona is generated from its pinned repo rather than
17495
+ // committed here, so an un-hydrated checkout is the likeliest cause and
17496
+ // "run from your checkout" would send the reader the wrong way.
17497
+ hint: agentContentHint(resolvedRoot ?? args.repoRoot, args.persona) ?? "Run from your m8t repo checkout, or pass --repo-root.",
17096
17498
  cause: e
17097
17499
  });
17098
17500
  }
17099
17501
  const fmMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
17100
- const fm = fmMatch ? parseYaml6(fmMatch[1]) : {};
17502
+ const fm = fmMatch ? parseYaml7(fmMatch[1]) : {};
17101
17503
  const model = args.model ?? fm.targets?.foundry?.model;
17102
17504
  if (!model) {
17103
17505
  throw new LocalCliError({
@@ -17271,14 +17673,14 @@ init_errors();
17271
17673
  // src/lib/agent-remove.ts
17272
17674
  init_errors();
17273
17675
  init_foundry_agent_get();
17274
- import * as fs15 from "fs";
17676
+ import * as fs18 from "fs";
17275
17677
  import { spawnSync as spawnSync2 } from "child_process";
17276
17678
 
17277
17679
  // src/lib/a2a-enable.ts
17278
17680
  init_errors();
17279
17681
  init_foundry_agent_get();
17280
17682
  init_foundry_agent_version();
17281
- import { randomBytes as randomBytes2, createHash } from "crypto";
17683
+ import { randomBytes as randomBytes2, createHash as createHash2 } from "crypto";
17282
17684
 
17283
17685
  // src/lib/data-plane-ready.ts
17284
17686
  init_errors();
@@ -17386,18 +17788,18 @@ async function awaitAgentQueryable(args) {
17386
17788
  // src/lib/persona-a2a.ts
17387
17789
  init_errors();
17388
17790
  init_esm();
17389
- import * as fs14 from "fs";
17390
- import { parse as parseYaml7 } from "yaml";
17791
+ import * as fs17 from "fs";
17792
+ import { parse as parseYaml8 } from "yaml";
17391
17793
  function readPersonaA2aCard(personaPath) {
17392
17794
  let raw;
17393
17795
  try {
17394
- raw = fs14.readFileSync(personaPath, "utf8");
17796
+ raw = fs17.readFileSync(personaPath, "utf8");
17395
17797
  } catch (e) {
17396
17798
  throw new LocalCliError({ code: "PERSONA_READ_FAILED", message: `Could not read persona '${personaPath}': ${e.message}` });
17397
17799
  }
17398
17800
  const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
17399
17801
  if (!fm) throw new LocalCliError({ code: "PERSONA_NO_FRONTMATTER", message: `Persona '${personaPath}' has no frontmatter.` });
17400
- const front = parseYaml7(fm[1]);
17802
+ const front = parseYaml8(fm[1]);
17401
17803
  const role = typeof front.role === "string" ? front.role : "";
17402
17804
  const cardYaml = front.targets?.foundry?.["a2a-card"];
17403
17805
  if (!cardYaml || typeof cardYaml !== "object") {
@@ -17459,7 +17861,7 @@ async function enableA2a(args) {
17459
17861
  });
17460
17862
  }
17461
17863
  const bearer2 = `a2a_${randomBytes2(32).toString("base64url")}`;
17462
- const bearerHash = createHash("sha256").update(bearer2).digest("hex");
17864
+ const bearerHash = createHash2("sha256").update(bearer2).digest("hex");
17463
17865
  progress("Provisioning the A2A connection\u2026");
17464
17866
  await putA2aConnection({ credential: args.credential, projectArmId: args.projectArmId, connectionName, target: args.bridgeUrl, bearer: bearer2 });
17465
17867
  progress("Deploying the a2a-enabled agent version\u2026");
@@ -17716,7 +18118,7 @@ function defaultRemoveAgentDeps(args) {
17716
18118
  },
17717
18119
  removeLocalYaml(agentName) {
17718
18120
  const p = agentYamlPath(agentName, home);
17719
- if (fs15.existsSync(p)) fs15.rmSync(p);
18121
+ if (fs18.existsSync(p)) fs18.rmSync(p);
17720
18122
  }
17721
18123
  };
17722
18124
  }
@@ -17858,17 +18260,17 @@ ${colors.success("\u2713")} removed ${colors.field(name)}.
17858
18260
  };
17859
18261
 
17860
18262
  // src/commands/a2a/enable.ts
17861
- import * as path15 from "path";
18263
+ import * as path18 from "path";
17862
18264
  import { Command as Command26, Option as Option25 } from "clipanion";
17863
18265
  import { DefaultAzureCredential as DefaultAzureCredential11 } from "@azure/identity";
17864
18266
  init_errors();
17865
18267
 
17866
18268
  // src/lib/bridge-url.ts
17867
18269
  init_errors();
17868
- import * as fs16 from "fs";
17869
- import * as os6 from "os";
17870
- import * as path14 from "path";
17871
- import { parse as parseYaml8 } from "yaml";
18270
+ import * as fs19 from "fs";
18271
+ import * as os7 from "os";
18272
+ import * as path17 from "path";
18273
+ import { parse as parseYaml9 } from "yaml";
17872
18274
  var A2A_PATH = "/api/a2a/mcp";
17873
18275
  function resolveBridgeUrl(opts) {
17874
18276
  const env = opts.env ?? process.env;
@@ -17889,10 +18291,10 @@ function clean(v) {
17889
18291
  return t.length ? t : void 0;
17890
18292
  }
17891
18293
  function readConfigGatewayUrl(home) {
17892
- const cfg = path14.join(home ?? os6.homedir(), ".m8t", "config.yaml");
17893
- if (!fs16.existsSync(cfg)) return void 0;
18294
+ const cfg = path17.join(home ?? os7.homedir(), ".m8t", "config.yaml");
18295
+ if (!fs19.existsSync(cfg)) return void 0;
17894
18296
  try {
17895
- const o = parseYaml8(fs16.readFileSync(cfg, "utf8"));
18297
+ const o = parseYaml9(fs19.readFileSync(cfg, "utf8"));
17896
18298
  return typeof o.gatewayUrl === "string" ? o.gatewayUrl : void 0;
17897
18299
  } catch {
17898
18300
  return void 0;
@@ -17961,11 +18363,11 @@ var A2aEnableCommand = class extends M8tCommand {
17961
18363
  resolvePersonaPath() {
17962
18364
  if (typeof this.persona === "string" && this.persona.length > 0) {
17963
18365
  if (this.persona.includes("/") || this.persona.endsWith(".md")) return this.persona;
17964
- return path15.join(resolveRepoRoot(), "personas", this.persona, "persona.md");
18366
+ return path18.join(resolveRepoRoot(), "personas", this.persona, "persona.md");
17965
18367
  }
17966
18368
  const yaml = readAgentYaml(this.worker);
17967
18369
  if (yaml?.personaPath) {
17968
- return yaml.personaPath.startsWith("/") ? yaml.personaPath : path15.join(resolveRepoRoot(), yaml.personaPath);
18370
+ return yaml.personaPath.startsWith("/") ? yaml.personaPath : path18.join(resolveRepoRoot(), yaml.personaPath);
17969
18371
  }
17970
18372
  throw new LocalCliError({ code: "A2A_NO_PERSONA", message: `Could not resolve a persona for '${this.worker}'. Pass --persona <name>.` });
17971
18373
  }
@@ -18020,13 +18422,13 @@ var A2aDisableCommand = class extends M8tCommand {
18020
18422
  import { Command as Command28 } from "clipanion";
18021
18423
 
18022
18424
  // src/lib/architect-version.ts
18023
- import { createHash as createHash2 } from "crypto";
18024
- import * as fs17 from "fs";
18025
- import * as os7 from "os";
18026
- import * as path16 from "path";
18425
+ import { createHash as createHash3 } from "crypto";
18426
+ import * as fs20 from "fs";
18427
+ import * as os8 from "os";
18428
+ import * as path19 from "path";
18027
18429
  function readVersionFrontmatter(file) {
18028
- if (!fs17.existsSync(file)) return "";
18029
- const text = fs17.readFileSync(file, "utf8");
18430
+ if (!fs20.existsSync(file)) return "";
18431
+ const text = fs20.readFileSync(file, "utf8");
18030
18432
  if (!text.startsWith("---")) return "";
18031
18433
  const closeIdx = text.indexOf("\n---", 3);
18032
18434
  if (closeIdx < 0) return "";
@@ -18035,27 +18437,27 @@ function readVersionFrontmatter(file) {
18035
18437
  return m ? m[1].trim() : "";
18036
18438
  }
18037
18439
  function sha256File(filePath) {
18038
- return createHash2("sha256").update(fs17.readFileSync(filePath)).digest("hex");
18440
+ return createHash3("sha256").update(fs20.readFileSync(filePath)).digest("hex");
18039
18441
  }
18040
18442
  var SIDECAR_FILENAME = "m8t-architect.m8t-skill.json";
18041
18443
  var LEGACY_SIDECAR_FILENAME = ".m8t-skill.json";
18042
18444
  function vsCodeUserDataDir() {
18043
18445
  if (process.platform === "darwin") {
18044
- return path16.join(os7.homedir(), "Library", "Application Support", "Code", "User");
18446
+ return path19.join(os8.homedir(), "Library", "Application Support", "Code", "User");
18045
18447
  }
18046
18448
  if (process.platform === "win32") {
18047
- const appData = process.env.APPDATA ?? path16.join(os7.homedir(), "AppData", "Roaming");
18048
- return path16.join(appData, "Code", "User");
18449
+ const appData = process.env.APPDATA ?? path19.join(os8.homedir(), "AppData", "Roaming");
18450
+ return path19.join(appData, "Code", "User");
18049
18451
  }
18050
18452
  return null;
18051
18453
  }
18052
18454
  function vsCodePromptsDir() {
18053
18455
  const userData = vsCodeUserDataDir();
18054
18456
  if (!userData) return null;
18055
- const prompts = path16.join(userData, "prompts");
18056
- if (fs17.existsSync(prompts)) return prompts;
18057
- const promptFiles = path16.join(userData, "prompt-files");
18058
- if (fs17.existsSync(promptFiles)) return promptFiles;
18457
+ const prompts = path19.join(userData, "prompts");
18458
+ if (fs20.existsSync(prompts)) return prompts;
18459
+ const promptFiles = path19.join(userData, "prompt-files");
18460
+ if (fs20.existsSync(promptFiles)) return promptFiles;
18059
18461
  return prompts;
18060
18462
  }
18061
18463
  var COPILOT_CLI_SKILLS_ROOTS = [
@@ -18064,9 +18466,9 @@ var COPILOT_CLI_SKILLS_ROOTS = [
18064
18466
  [".github", "copilot", "skills"]
18065
18467
  ];
18066
18468
  function sidecarLocations() {
18067
- const home = os7.homedir();
18469
+ const home = os8.homedir();
18068
18470
  const locations = [
18069
- { host: "Claude Code", dir: path16.join(home, ".claude", "skills", "m8t-architect") }
18471
+ { host: "Claude Code", dir: path19.join(home, ".claude", "skills", "m8t-architect") }
18070
18472
  ];
18071
18473
  const vsCodeDir = vsCodePromptsDir();
18072
18474
  if (vsCodeDir) {
@@ -18075,7 +18477,7 @@ function sidecarLocations() {
18075
18477
  for (const segments of COPILOT_CLI_SKILLS_ROOTS) {
18076
18478
  locations.push({
18077
18479
  host: "GitHub Copilot CLI",
18078
- dir: path16.join(home, ...segments, "m8t-architect")
18480
+ dir: path19.join(home, ...segments, "m8t-architect")
18079
18481
  });
18080
18482
  }
18081
18483
  return locations;
@@ -18084,10 +18486,10 @@ function resolveSidecar() {
18084
18486
  let best = null;
18085
18487
  for (const loc of sidecarLocations()) {
18086
18488
  for (const filename of [SIDECAR_FILENAME, LEGACY_SIDECAR_FILENAME]) {
18087
- const candidate2 = path16.join(loc.dir, filename);
18489
+ const candidate2 = path19.join(loc.dir, filename);
18088
18490
  let mtimeMs;
18089
18491
  try {
18090
- mtimeMs = fs17.statSync(candidate2).mtimeMs;
18492
+ mtimeMs = fs20.statSync(candidate2).mtimeMs;
18091
18493
  } catch {
18092
18494
  continue;
18093
18495
  }
@@ -18099,13 +18501,13 @@ function resolveSidecar() {
18099
18501
  return best;
18100
18502
  }
18101
18503
  function checkArchitectDrift() {
18102
- const sourcePath = path16.join(
18504
+ const sourcePath = path19.join(
18103
18505
  resolveRepoRoot(),
18104
18506
  "personas",
18105
18507
  "m8t-architect",
18106
18508
  "persona.md"
18107
18509
  );
18108
- if (!fs17.existsSync(sourcePath)) {
18510
+ if (!fs20.existsSync(sourcePath)) {
18109
18511
  return {
18110
18512
  match: false,
18111
18513
  sourceVersion: "",
@@ -18118,7 +18520,7 @@ function checkArchitectDrift() {
18118
18520
  let sidecar = null;
18119
18521
  if (resolved) {
18120
18522
  try {
18121
- const raw = JSON.parse(fs17.readFileSync(resolved.path, "utf8"));
18523
+ const raw = JSON.parse(fs20.readFileSync(resolved.path, "utf8"));
18122
18524
  if (raw !== null && typeof raw === "object") {
18123
18525
  const r = raw;
18124
18526
  sidecar = {
@@ -18180,10 +18582,123 @@ var ArchitectCheckCommand = class extends M8tCommand {
18180
18582
  }
18181
18583
  };
18182
18584
 
18585
+ // src/commands/agent-content/sync.ts
18586
+ import { Command as Command29, Option as Option27 } from "clipanion";
18587
+ import * as path20 from "path";
18588
+ var AgentContentSyncCommand = class extends M8tCommand {
18589
+ static paths = [["agent-content", "sync"]];
18590
+ static usage = Command29.Usage({
18591
+ description: "Materialize the pinned agent repos into personas/ and brain-seeds/.",
18592
+ details: "Reads installer/release-pin.json, fetches each pinned agent repo at its pinned commit, verifies the content against the pin's contentSha, and writes personas/<persona>/ + brain-seeds/<persona>/ under the repo root. Those paths are git-ignored: the agent repos are the source of truth, and this is how a checkout gets a usable copy. Private agent repos need AGENT_CONTENT_TOKEN (or GH_TOKEN / GITHUB_TOKEN / an authed gh). See docs/architecture/AGENT-REPO-CONTRACT.md.",
18593
+ examples: [
18594
+ ["Sync into the current checkout", "$0 agent-content sync"],
18595
+ ["Sync into an explicit root", "$0 agent-content sync --root /opt/m8t/repo"]
18596
+ ]
18597
+ });
18598
+ root = Option27.String("--root", { description: "Repo root to hydrate into. Defaults to the m8t checkout." });
18599
+ async executeCommand() {
18600
+ const root = (typeof this.root === "string" ? this.root : void 0) ?? tryResolveRepoRoot() ?? process.cwd();
18601
+ const synced = await syncAgentContent({
18602
+ root: path20.resolve(root),
18603
+ deps: { env: this.context.env, onNotice: (m) => this.context.stderr.write(` ${colors.dim(m)}
18604
+ `) }
18605
+ });
18606
+ if (synced.length === 0) {
18607
+ this.context.stdout.write(`${colors.hint("note:")} the release pin declares no agents \u2014 nothing to sync.
18608
+ `);
18609
+ return 0;
18610
+ }
18611
+ for (const a of synced) {
18612
+ this.context.stdout.write(
18613
+ `${colors.success("\u2713")} ${colors.field(a.persona)} \u2190 ${a.repo}@${a.ref.slice(0, 8)} (${colors.dim(`personas/${a.persona}/, brain-seeds/${a.persona}/`)})
18614
+ `
18615
+ );
18616
+ }
18617
+ return 0;
18618
+ }
18619
+ };
18620
+
18621
+ // src/commands/agent-content/pin.ts
18622
+ import { Command as Command30, Option as Option28 } from "clipanion";
18623
+ import * as fs21 from "fs";
18624
+ import * as path21 from "path";
18625
+ init_errors();
18626
+ var AgentContentPinCommand = class extends M8tCommand {
18627
+ static paths = [["agent-content", "pin"]];
18628
+ static usage = Command30.Usage({
18629
+ description: "Re-derive a pinned agent's ref + contentSha from its branch.",
18630
+ details: "Resolves <key>'s repo branch to an immutable commit, fetches THAT commit, and digests what it actually contains \u2014 so the recorded contentSha describes bytes that were read, not a branch that may have moved. Prints the new entry; --write applies it to installer/release-pin.json. Bumping a pin is a release act: it changes what a from-zero install deploys.",
18631
+ examples: [
18632
+ ["Show what ezra's pin would become", "$0 agent-content pin ezra"],
18633
+ ["Apply it", "$0 agent-content pin ezra --write"],
18634
+ ["Pin a non-default branch", "$0 agent-content pin ezra --branch curated"]
18635
+ ]
18636
+ });
18637
+ key = Option28.String();
18638
+ branch = Option28.String("--branch", { description: "Branch to resolve. Default: main." });
18639
+ write = Option28.Boolean("--write", false, { description: "Apply the new entry to installer/release-pin.json." });
18640
+ root = Option28.String("--root");
18641
+ output = Option28.String("--output");
18642
+ async executeCommand() {
18643
+ const key2 = typeof this.key === "string" ? this.key : void 0;
18644
+ if (!key2) throw new LocalCliError({ code: "USAGE", message: "<key> is required (an agents.<key> from the release pin)" });
18645
+ const branch = (typeof this.branch === "string" ? this.branch : void 0) ?? "main";
18646
+ const root = path21.resolve(
18647
+ (typeof this.root === "string" ? this.root : void 0) ?? tryResolveRepoRoot() ?? process.cwd()
18648
+ );
18649
+ const pinPath = path21.join(root, PIN_REL_PATH);
18650
+ const raw = fs21.readFileSync(pinPath, "utf8");
18651
+ const pin = parseReleasePin(raw, pinPath);
18652
+ if (!Object.hasOwn(pin.agents, key2)) {
18653
+ throw new LocalCliError({
18654
+ code: "AGENT_PIN_UNKNOWN",
18655
+ message: `No agents.${key2} in ${PIN_REL_PATH}.`,
18656
+ hint: `Known keys: ${Object.keys(pin.agents).join(", ") || "(none)"}.`
18657
+ });
18658
+ }
18659
+ const current = pin.agents[key2];
18660
+ const next = await derivePin({
18661
+ current,
18662
+ branch,
18663
+ deps: { env: this.context.env, onNotice: (m) => this.context.stderr.write(` ${colors.dim(m)}
18664
+ `) }
18665
+ });
18666
+ if (this.output === "json") {
18667
+ this.context.stdout.write(renderJson({ key: key2, branch, from: current, to: next }) + "\n");
18668
+ } else if (next.ref === current.ref && next.contentSha === current.contentSha && next.persona === current.persona) {
18669
+ this.context.stdout.write(`${colors.success("\u2713")} ${key2} is already pinned to ${branch} (${next.ref.slice(0, 8)}).
18670
+ `);
18671
+ } else {
18672
+ this.context.stdout.write(`${colors.field(key2)} \u2192 ${branch}
18673
+ `);
18674
+ const line2 = (label, a, b) => {
18675
+ this.context.stdout.write(
18676
+ a === b ? ` ${colors.dim(`${label}: ${a} (unchanged)`)}
18677
+ ` : ` ${label}: ${colors.dim(a)} \u2192 ${colors.field(b)}
18678
+ `
18679
+ );
18680
+ };
18681
+ line2("ref ", current.ref, next.ref);
18682
+ line2("contentSha", current.contentSha, next.contentSha);
18683
+ line2("persona ", current.persona, next.persona);
18684
+ }
18685
+ if (this.write === true) {
18686
+ const doc = JSON.parse(raw);
18687
+ doc.agents[key2] = { repo: next.repo, ref: next.ref, visibility: next.visibility, persona: next.persona, contentSha: next.contentSha };
18688
+ fs21.writeFileSync(pinPath, JSON.stringify(doc, null, 2) + "\n");
18689
+ this.context.stdout.write(`${colors.success("\u2713")} wrote ${PIN_REL_PATH}
18690
+ `);
18691
+ this.context.stdout.write(` ${colors.hint("note:")} bumping a pin is a release act \u2014 it changes what a from-zero install deploys.
18692
+ `);
18693
+ }
18694
+ return 0;
18695
+ }
18696
+ };
18697
+
18183
18698
  // src/commands/coder/deploy.ts
18184
18699
  init_esm2();
18185
- import * as path18 from "path";
18186
- import { Command as Command29, Option as Option27 } from "clipanion";
18700
+ import * as path23 from "path";
18701
+ import { Command as Command31, Option as Option29 } from "clipanion";
18187
18702
  import { DefaultAzureCredential as DefaultAzureCredential13 } from "@azure/identity";
18188
18703
  init_errors();
18189
18704
  init_foundry_agent_get();
@@ -18449,14 +18964,14 @@ async function deployHostedWorker(args) {
18449
18964
  }
18450
18965
 
18451
18966
  // src/lib/persona.ts
18452
- import * as fs18 from "fs";
18453
- import * as path17 from "path";
18454
- import { parse as parseYaml9 } from "yaml";
18967
+ import * as fs22 from "fs";
18968
+ import * as path22 from "path";
18969
+ import { parse as parseYaml10 } from "yaml";
18455
18970
  function findRepoRoot(startDir) {
18456
- let dir = path17.resolve(startDir);
18971
+ let dir = path22.resolve(startDir);
18457
18972
  for (; ; ) {
18458
- if (fs18.existsSync(path17.join(dir, "personas"))) return dir;
18459
- const parent = path17.dirname(dir);
18973
+ if (fs22.existsSync(path22.join(dir, "personas"))) return dir;
18974
+ const parent = path22.dirname(dir);
18460
18975
  if (parent === dir) return null;
18461
18976
  dir = parent;
18462
18977
  }
@@ -18464,10 +18979,10 @@ function findRepoRoot(startDir) {
18464
18979
  function resolvePersona(persona, cwd = process.cwd()) {
18465
18980
  const root = findRepoRoot(cwd);
18466
18981
  if (!root) return { persona, personaVersion: null };
18467
- const file = path17.join(root, "personas", persona, "persona.md");
18982
+ const file = path22.join(root, "personas", persona, "persona.md");
18468
18983
  let raw;
18469
18984
  try {
18470
- raw = fs18.readFileSync(file, "utf-8");
18985
+ raw = fs22.readFileSync(file, "utf-8");
18471
18986
  } catch {
18472
18987
  return { persona, personaVersion: null };
18473
18988
  }
@@ -18475,7 +18990,7 @@ function resolvePersona(persona, cwd = process.cwd()) {
18475
18990
  if (!match) return { persona, personaVersion: null };
18476
18991
  let fm = null;
18477
18992
  try {
18478
- fm = parseYaml9(match[1]);
18993
+ fm = parseYaml10(match[1]);
18479
18994
  } catch {
18480
18995
  return { persona, personaVersion: null };
18481
18996
  }
@@ -18611,7 +19126,7 @@ var DEFAULT_MODEL = "gpt-4.1-mini";
18611
19126
  var NAME_RE = /^[a-z0-9-]+$/;
18612
19127
  var CoderDeployCommand = class extends M8tCommand {
18613
19128
  static paths = [["coder", "deploy"]];
18614
- static usage = Command29.Usage({
19129
+ static usage = Command31.Usage({
18615
19130
  description: "Deploy the curated coding agent as a hosted Foundry worker.",
18616
19131
  details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-labs/m8t-coding-agent). Post-2026-06-25 Foundry projects require an authenticated pull, so a public image is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 a server-side copy, no local build) and the agent is deployed from that ACR ref. Re-running with a newer --image-tag imports the new tag and rolls out a new agent version \u2014 that is how you update a worker's image. Override --image with a private ACR ref to bring your own registry.",
18617
19132
  examples: [
@@ -18620,22 +19135,22 @@ var CoderDeployCommand = class extends M8tCommand {
18620
19135
  ["Override the exec timeout", "$0 coder deploy my-coder --env M8T_CODER_EXEC_TIMEOUT_SECONDS=300"]
18621
19136
  ]
18622
19137
  });
18623
- name = Option27.String();
18624
- persona = Option27.String("--persona");
18625
- image = Option27.String("--image");
18626
- imageTag = Option27.String("--image-tag");
18627
- size = Option27.String("--size");
18628
- modelDeployment = Option27.String("--model-deployment");
18629
- env = Option27.Array("--env");
18630
- endpoint = Option27.String("--endpoint");
18631
- subscription = Option27.String("--subscription");
18632
- output = Option27.String("--output");
18633
- brain = Option27.String("--brain");
18634
- brainBranch = Option27.String("--branch");
18635
- brainKv = Option27.String("--brain-kv");
18636
- allowNonReasoning = Option27.Boolean("--allow-non-reasoning", false);
18637
- skipQuotaCheck = Option27.Boolean("--skip-quota-check", false);
18638
- gatewayUrl = Option27.String("--gateway-url", { description: "Base gateway URL for the a2a bridge (e.g. https://<gateway-fqdn>); enables this coder as an a2a target." });
19138
+ name = Option29.String();
19139
+ persona = Option29.String("--persona");
19140
+ image = Option29.String("--image");
19141
+ imageTag = Option29.String("--image-tag");
19142
+ size = Option29.String("--size");
19143
+ modelDeployment = Option29.String("--model-deployment");
19144
+ env = Option29.Array("--env");
19145
+ endpoint = Option29.String("--endpoint");
19146
+ subscription = Option29.String("--subscription");
19147
+ output = Option29.String("--output");
19148
+ brain = Option29.String("--brain");
19149
+ brainBranch = Option29.String("--branch");
19150
+ brainKv = Option29.String("--brain-kv");
19151
+ allowNonReasoning = Option29.Boolean("--allow-non-reasoning", false);
19152
+ skipQuotaCheck = Option29.Boolean("--skip-quota-check", false);
19153
+ gatewayUrl = Option29.String("--gateway-url", { description: "Base gateway URL for the a2a bridge (e.g. https://<gateway-fqdn>); enables this coder as an a2a target." });
18639
19154
  async executeCommand() {
18640
19155
  if (!NAME_RE.test(this.name)) {
18641
19156
  throw new LocalCliError({
@@ -18824,7 +19339,7 @@ var CoderDeployCommand = class extends M8tCommand {
18824
19339
  projectEndpoint: project.endpoint,
18825
19340
  projectArmId: `${project.accountScope}/projects/${project.projectName}`,
18826
19341
  agentName: this.name,
18827
- personaPath: path18.join(resolveRepoRoot(), "personas", personaName, "persona.md"),
19342
+ personaPath: path23.join(resolveRepoRoot(), "personas", personaName, "persona.md"),
18828
19343
  bridgeUrl,
18829
19344
  onProgress
18830
19345
  });
@@ -18869,13 +19384,13 @@ var CoderDeployCommand = class extends M8tCommand {
18869
19384
 
18870
19385
  // src/commands/coder/teardown.ts
18871
19386
  import { confirm as confirm4 } from "@inquirer/prompts";
18872
- import { Command as Command30, Option as Option28 } from "clipanion";
19387
+ import { Command as Command32, Option as Option30 } from "clipanion";
18873
19388
  import { DefaultAzureCredential as DefaultAzureCredential14 } from "@azure/identity";
18874
19389
  init_foundry_agents();
18875
19390
  init_errors();
18876
19391
  var CoderTeardownCommand = class extends M8tCommand {
18877
19392
  static paths = [["coder", "teardown"]];
18878
- static usage = Command30.Usage({
19393
+ static usage = Command32.Usage({
18879
19394
  description: "Delete a deployed hosted coder (removes its container + identity + role assignment).",
18880
19395
  details: "Idempotent: tearing down a missing coder reports 'already gone'. Only the named agent is touched. Discovery self-heals on the next worker list.",
18881
19396
  examples: [
@@ -18883,11 +19398,11 @@ var CoderTeardownCommand = class extends M8tCommand {
18883
19398
  ["Skip the confirm (scripts)", "$0 coder teardown my-coder --yes"]
18884
19399
  ]
18885
19400
  });
18886
- name = Option28.String();
18887
- yes = Option28.Boolean("--yes", false);
18888
- endpoint = Option28.String("--endpoint");
18889
- subscription = Option28.String("--subscription");
18890
- output = Option28.String("--output");
19401
+ name = Option30.String();
19402
+ yes = Option30.Boolean("--yes", false);
19403
+ endpoint = Option30.String("--endpoint");
19404
+ subscription = Option30.String("--subscription");
19405
+ output = Option30.String("--output");
18891
19406
  async executeCommand() {
18892
19407
  const mode = resolveOutputMode(
18893
19408
  this.output,
@@ -18951,8 +19466,8 @@ var CoderTeardownCommand = class extends M8tCommand {
18951
19466
 
18952
19467
  // src/commands/azure-exec/deploy.ts
18953
19468
  init_esm2();
18954
- import * as path19 from "path";
18955
- import { Command as Command31, Option as Option29 } from "clipanion";
19469
+ import * as path24 from "path";
19470
+ import { Command as Command33, Option as Option31 } from "clipanion";
18956
19471
  import { DefaultAzureCredential as DefaultAzureCredential15 } from "@azure/identity";
18957
19472
  init_errors();
18958
19473
  init_foundry_agent_get();
@@ -19014,7 +19529,7 @@ var DEFAULT_MODEL2 = "gpt-5-mini";
19014
19529
  var NAME_RE2 = /^[a-z0-9-]+$/;
19015
19530
  var AzureExecDeployCommand = class extends M8tCommand {
19016
19531
  static paths = [["azure-exec", "deploy"]];
19017
- static usage = Command31.Usage({
19532
+ static usage = Command33.Usage({
19018
19533
  description: "Deploy the Azure executor as a hosted Foundry worker (az CLI + tiered ops).",
19019
19534
  details: "Creates a hosted agent version from a container image (defaults to the public GHCR image ghcr.io/m8t-labs/m8t-azure-executor \u2014 no local build needed), grants its identity Foundry User + Contributor (at --scope) + Key Vault Secrets User (brain KV), polls to active, and a2a-enables it as a target. Override with --image/--image-tag for a bring-your-own-registry image (e.g. a private ACR ref, which must be pushed first). Contributor scope is REQUIRED \u2014 pass --scope or --resource-group. Pass --grant-access-admin to additionally grant User Access Administrator (enables human-approved Tier-2 role/delete ops). Post-2026-06-25 Foundry projects require an authenticated pull, so the public image (default ghcr.io/m8t-labs/m8t-azure-executor) is staged into the customer's Azure Container Registry first (created if missing, then `az acr import` \u2014 server-side, no local build) and deployed from that ACR ref; re-running with a newer --image-tag updates the image.",
19020
19535
  examples: [
@@ -19024,23 +19539,23 @@ var AzureExecDeployCommand = class extends M8tCommand {
19024
19539
  ]
19025
19540
  ]
19026
19541
  });
19027
- name = Option29.String();
19028
- image = Option29.String("--image");
19029
- imageTag = Option29.String("--image-tag");
19030
- size = Option29.String("--size");
19031
- scope = Option29.String("--scope");
19032
- resourceGroup = Option29.String("--resource-group");
19033
- modelDeployment = Option29.String("--model-deployment");
19034
- env = Option29.Array("--env");
19035
- brain = Option29.String("--brain");
19036
- kvUri = Option29.String("--kv-uri");
19037
- gatewayUrl = Option29.String("--gateway-url");
19038
- endpoint = Option29.String("--endpoint");
19039
- subscription = Option29.String("--subscription");
19040
- output = Option29.String("--output");
19041
- skipQuotaCheck = Option29.Boolean("--skip-quota-check", false);
19042
- grantAccessAdmin = Option29.Boolean("--grant-access-admin", false);
19043
- enableEmail = Option29.Boolean("--enable-email", false);
19542
+ name = Option31.String();
19543
+ image = Option31.String("--image");
19544
+ imageTag = Option31.String("--image-tag");
19545
+ size = Option31.String("--size");
19546
+ scope = Option31.String("--scope");
19547
+ resourceGroup = Option31.String("--resource-group");
19548
+ modelDeployment = Option31.String("--model-deployment");
19549
+ env = Option31.Array("--env");
19550
+ brain = Option31.String("--brain");
19551
+ kvUri = Option31.String("--kv-uri");
19552
+ gatewayUrl = Option31.String("--gateway-url");
19553
+ endpoint = Option31.String("--endpoint");
19554
+ subscription = Option31.String("--subscription");
19555
+ output = Option31.String("--output");
19556
+ skipQuotaCheck = Option31.Boolean("--skip-quota-check", false);
19557
+ grantAccessAdmin = Option31.Boolean("--grant-access-admin", false);
19558
+ enableEmail = Option31.Boolean("--enable-email", false);
19044
19559
  async executeCommand() {
19045
19560
  if (!NAME_RE2.test(this.name)) {
19046
19561
  throw new LocalCliError({
@@ -19227,7 +19742,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
19227
19742
  kvUri
19228
19743
  });
19229
19744
  onProgress?.("a2a-enabling as a target\u2026");
19230
- const personaPath = path19.join(resolveRepoRoot(), "personas", "azure-executor", "persona.md");
19745
+ const personaPath = path24.join(resolveRepoRoot(), "personas", "azure-executor", "persona.md");
19231
19746
  const bridgeUrl = resolveBridgeUrl({
19232
19747
  flag: typeof this.gatewayUrl === "string" ? this.gatewayUrl : void 0,
19233
19748
  env: processEnv
@@ -19285,7 +19800,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
19285
19800
  };
19286
19801
 
19287
19802
  // src/commands/platform/status.ts
19288
- import { Command as Command32, Option as Option30 } from "clipanion";
19803
+ import { Command as Command34, Option as Option32 } from "clipanion";
19289
19804
  import { DefaultAzureCredential as DefaultAzureCredential16 } from "@azure/identity";
19290
19805
 
19291
19806
  // src/lib/platform-update.ts
@@ -19393,8 +19908,8 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
19393
19908
  hint: "Pass a ghcr.io/<owner>/<name> repo, or use the BYOC private-ACR deploy flow."
19394
19909
  });
19395
19910
  }
19396
- const path43 = repo.replace(/^ghcr\.io\//, "");
19397
- const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${path43}:pull`);
19911
+ const path48 = repo.replace(/^ghcr\.io\//, "");
19912
+ const tokenRes = await fetchImpl(`https://ghcr.io/token?scope=repository:${path48}:pull`);
19398
19913
  if (!tokenRes.ok) {
19399
19914
  throw new LocalCliError({
19400
19915
  code: "PLATFORM_GHCR_TOKEN_FAILED",
@@ -19410,7 +19925,7 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
19410
19925
  hint: "Make the package public (deploy/ghcr-package-visibility.md), then retry."
19411
19926
  });
19412
19927
  }
19413
- const tagsRes = await fetchImpl(`https://ghcr.io/v2/${path43}/tags/list`, {
19928
+ const tagsRes = await fetchImpl(`https://ghcr.io/v2/${path48}/tags/list`, {
19414
19929
  headers: { Authorization: `Bearer ${token}` }
19415
19930
  });
19416
19931
  if (!tagsRes.ok) {
@@ -19424,7 +19939,7 @@ async function fetchPublicTags(repo, fetchImpl = fetch) {
19424
19939
  }
19425
19940
 
19426
19941
  // src/lib/release-channel.ts
19427
- import * as fs19 from "fs";
19942
+ import * as fs23 from "fs";
19428
19943
 
19429
19944
  // ../../packages/platform-release/dist/esm/manifest.js
19430
19945
  var SEVERITIES = ["critical", "recommended", "optional"];
@@ -19647,7 +20162,7 @@ function manifestSourceForVersionTag(channelUrl, version) {
19647
20162
  return { url: custom };
19648
20163
  }
19649
20164
  async function fetchManifest(source, deps = {}) {
19650
- const readFile9 = deps.readFile ?? ((p) => fs19.readFileSync(p, "utf8"));
20165
+ const readFile9 = deps.readFile ?? ((p) => fs23.readFileSync(p, "utf8"));
19651
20166
  const fetchImpl = deps.fetchImpl ?? fetch;
19652
20167
  const ghToken = deps.ghToken ?? getGhToken;
19653
20168
  let raw;
@@ -19693,10 +20208,9 @@ async function fetchManifest(source, deps = {}) {
19693
20208
  }
19694
20209
 
19695
20210
  // src/lib/release-content.ts
19696
- import * as fs20 from "fs";
19697
- import * as os8 from "os";
19698
- import * as path20 from "path";
19699
- import { execFileSync as execFileSync2 } from "child_process";
20211
+ import * as fs24 from "fs";
20212
+ import * as os9 from "os";
20213
+ import * as path25 from "path";
19700
20214
  init_errors();
19701
20215
  var OWNER_REPO = "m8t-labs/m8t";
19702
20216
  function parseTreeResponse(body) {
@@ -19725,8 +20239,13 @@ async function fetchRepoTree(commit, deps = {}) {
19725
20239
  function verifyPersonaTrees(manifest, tree) {
19726
20240
  const out = [];
19727
20241
  for (const [name, item] of Object.entries(manifest.components.personas.items)) {
20242
+ if (item.source) continue;
19728
20243
  const actual = tree.treeShaOf(item.path);
19729
- if (actual !== void 0 && actual !== item.treeSha) {
20244
+ if (actual === void 0) {
20245
+ out.push(
20246
+ `persona '${name}' (${item.path}): the manifest claims it is in the platform repo at ${manifest.platform.commit}, but that commit's tree has no such path`
20247
+ );
20248
+ } else if (actual !== item.treeSha) {
19730
20249
  out.push(`persona '${name}' (${item.path}): manifest pins ${item.treeSha} but commit tree has ${actual}`);
19731
20250
  }
19732
20251
  }
@@ -19734,15 +20253,15 @@ function verifyPersonaTrees(manifest, tree) {
19734
20253
  }
19735
20254
  async function resolveReleaseContent(manifest, opts = {}) {
19736
20255
  if (opts.contentDir) {
19737
- if (!fs20.existsSync(path20.join(opts.contentDir, "personas"))) {
20256
+ if (!fs24.existsSync(path25.join(opts.contentDir, "personas"))) {
19738
20257
  throw new LocalCliError({ code: "PLATFORM_CONTENT_DIR_INVALID", message: `--content-dir '${opts.contentDir}' has no personas/ \u2014 not a repo checkout.` });
19739
20258
  }
19740
20259
  return opts.contentDir;
19741
20260
  }
19742
20261
  const commit = manifest.platform.commit;
19743
- const cacheRoot = opts.cacheRoot ?? path20.join(os8.homedir(), ".m8t", "cache");
19744
- const dest = path20.join(cacheRoot, `release-${commit}`);
19745
- if (fs20.existsSync(path20.join(dest, "personas"))) return dest;
20262
+ const cacheRoot = opts.cacheRoot ?? path25.join(os9.homedir(), ".m8t", "cache");
20263
+ const dest = path25.join(cacheRoot, `release-${commit}`);
20264
+ if (fs24.existsSync(path25.join(dest, "personas"))) return dest;
19746
20265
  const fetchImpl = opts.fetchImpl ?? fetch;
19747
20266
  const ghToken = opts.ghToken ?? getGhToken;
19748
20267
  let token;
@@ -19756,33 +20275,29 @@ async function resolveReleaseContent(manifest, opts = {}) {
19756
20275
  if (!res.ok) {
19757
20276
  throw new LocalCliError({ code: "PLATFORM_TARBALL_FETCH_FAILED", message: `GET ${url} \u2192 HTTP ${res.status.toString()}.` });
19758
20277
  }
19759
- fs20.mkdirSync(cacheRoot, { recursive: true });
19760
- const tmp = fs20.mkdtempSync(path20.join(cacheRoot, `.dl-${commit.slice(0, 8)}-`));
20278
+ fs24.mkdirSync(cacheRoot, { recursive: true });
20279
+ const tmp = fs24.mkdtempSync(path25.join(cacheRoot, `.dl-${commit.slice(0, 8)}-`));
19761
20280
  try {
19762
- const tgz = path20.join(tmp, "src.tar.gz");
19763
- fs20.writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
19764
- const unpacked = path20.join(tmp, "unpacked");
19765
- fs20.mkdirSync(unpacked);
20281
+ const tgz = path25.join(tmp, "src.tar.gz");
20282
+ fs24.writeFileSync(tgz, Buffer.from(await res.arrayBuffer()));
20283
+ const unpacked = path25.join(tmp, "unpacked");
20284
+ fs24.mkdirSync(unpacked);
19766
20285
  extractTarGz(tgz, unpacked);
19767
- try {
19768
- fs20.renameSync(unpacked, dest);
19769
- } catch (e) {
19770
- const err = e;
19771
- const isBenignRace = (err.code === "EEXIST" || err.code === "ENOTEMPTY") && fs20.existsSync(path20.join(dest, "personas"));
19772
- if (!isBenignRace) {
19773
- throw new LocalCliError({
19774
- code: "PLATFORM_CACHE_PUBLISH_FAILED",
19775
- message: `Could not publish release cache to ${dest}: ${err.message}`
19776
- });
19777
- }
19778
- }
20286
+ publishAtomically({
20287
+ from: unpacked,
20288
+ dest,
20289
+ sentinel: "personas",
20290
+ errorCode: "PLATFORM_CACHE_PUBLISH_FAILED"
20291
+ });
19779
20292
  } finally {
19780
- fs20.rmSync(tmp, { recursive: true, force: true });
20293
+ fs24.rmSync(tmp, { recursive: true, force: true });
19781
20294
  }
19782
20295
  return dest;
19783
20296
  }
19784
- function extractTarGz(tgz, into) {
19785
- execFileSync2("tar", ["-xzf", tgz, "-C", into, "--strip-components=1"]);
20297
+ async function resolveReleaseContentWithAgents(manifest, opts = {}) {
20298
+ const contentDir = await resolveReleaseContent(manifest, opts);
20299
+ await hydrateAgentsInto(contentDir, manifest.components.agents ?? {}, opts.agentDeps);
20300
+ return contentDir;
19786
20301
  }
19787
20302
 
19788
20303
  // src/lib/platform-stamp.ts
@@ -19934,14 +20449,14 @@ async function readStamp(opts) {
19934
20449
 
19935
20450
  // src/lib/platform-converge.ts
19936
20451
  init_esm();
19937
- import * as fs22 from "fs";
19938
- import * as path22 from "path";
19939
- import { parse as parseYaml10 } from "yaml";
20452
+ import * as fs26 from "fs";
20453
+ import * as path27 from "path";
20454
+ import { parse as parseYaml11 } from "yaml";
19940
20455
 
19941
20456
  // src/lib/deploy.ts
19942
- import * as fs21 from "fs/promises";
19943
- import * as os9 from "os";
19944
- import * as path21 from "path";
20457
+ import * as fs25 from "fs/promises";
20458
+ import * as os10 from "os";
20459
+ import * as path26 from "path";
19945
20460
  init_errors();
19946
20461
  var FOUNDRY_TRACING_MODES = ["project", "account", "skip"];
19947
20462
  function parseFoundryTracingMode(v) {
@@ -19999,10 +20514,10 @@ function buildBicepParams(p) {
19999
20514
  if (p.examApiBase) params.push(`examApiBase=${p.examApiBase}`);
20000
20515
  return params;
20001
20516
  }
20002
- async function resolveRepoRoot2(home = os9.homedir()) {
20003
- const marker = path21.join(home, ".m8t", "repo-root");
20517
+ async function resolveRepoRoot2(home = os10.homedir()) {
20518
+ const marker = path26.join(home, ".m8t", "repo-root");
20004
20519
  try {
20005
- const root = (await fs21.readFile(marker, "utf8")).trim();
20520
+ const root = (await fs25.readFile(marker, "utf8")).trim();
20006
20521
  if (!root) throw new Error("empty");
20007
20522
  return root;
20008
20523
  } catch {
@@ -20088,7 +20603,7 @@ function buildDeployResult(args) {
20088
20603
  };
20089
20604
  }
20090
20605
  async function runBicepDeployment(opts) {
20091
- const bicepPath = path21.join(opts.repoRoot, "deploy", "main.bicep");
20606
+ const bicepPath = path26.join(opts.repoRoot, "deploy", "main.bicep");
20092
20607
  const result2 = JSON.parse(
20093
20608
  await runAz([
20094
20609
  "deployment",
@@ -20455,14 +20970,14 @@ async function applyAgentImage(a, ctx, opts) {
20455
20970
  function declaredFillableFields(personaPath) {
20456
20971
  let raw;
20457
20972
  try {
20458
- raw = fs22.readFileSync(personaPath, "utf8");
20973
+ raw = fs26.readFileSync(personaPath, "utf8");
20459
20974
  } catch {
20460
20975
  return [];
20461
20976
  }
20462
20977
  const fmMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
20463
20978
  if (!fmMatch) return [];
20464
20979
  try {
20465
- const fm = parseYaml10(fmMatch[1]);
20980
+ const fm = parseYaml11(fmMatch[1]);
20466
20981
  return fm["fillable-fields"] ?? [];
20467
20982
  } catch {
20468
20983
  return [];
@@ -20481,7 +20996,7 @@ function injectAndRender(personaPath, values, agentName) {
20481
20996
  function loaderText(loaderPath) {
20482
20997
  if (!loaderPath) return null;
20483
20998
  try {
20484
- return fs22.readFileSync(loaderPath, "utf8");
20999
+ return fs26.readFileSync(loaderPath, "utf8");
20485
21000
  } catch {
20486
21001
  return null;
20487
21002
  }
@@ -20498,7 +21013,7 @@ function brainRepoOf(current) {
20498
21013
  }
20499
21014
  async function applyPersona(a, ctx, opts) {
20500
21015
  const current = await getAgentVersion({ credential: ctx.credential, projectEndpoint: opts.project.endpoint, agentName: opts.agentName });
20501
- const personaPath = path22.join(opts.personaDir, "persona.md");
21016
+ const personaPath = path27.join(opts.personaDir, "persona.md");
20502
21017
  const yamlValues = readAgentYaml(opts.agentName)?.fillableFieldValues ?? null;
20503
21018
  const values = resolveFillableValues(current, yamlValues);
20504
21019
  const declared = declaredFillableFields(personaPath);
@@ -20633,30 +21148,30 @@ async function readGatewayVersion(gatewayUrl, fetchImpl = fetch) {
20633
21148
  // src/commands/platform/status.ts
20634
21149
  var PlatformStatusCommand = class extends M8tCommand {
20635
21150
  static paths = [["platform", "status"]];
20636
- static usage = Command32.Usage({
21151
+ static usage = Command34.Usage({
20637
21152
  description: "Show per-component platform drift against a release manifest.",
20638
21153
  details: "Fetches a release manifest (the current channel by default), reads the installed-state stamp, and reports each component's installed vs target version and drift status. Read-only \u2014 never writes the stamp, never converges anything (use 'm8t platform update' for that). --verify additionally probes the live gateway (image tag + /api/version) best-effort."
20639
21154
  });
20640
- subscription = Option30.String("--subscription");
20641
- resourceGroup = Option30.String("--resource-group", {
21155
+ subscription = Option32.String("--subscription");
21156
+ resourceGroup = Option32.String("--resource-group", {
20642
21157
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
20643
21158
  });
20644
- to = Option30.String("--to", {
21159
+ to = Option32.String("--to", {
20645
21160
  description: "Check status against a pinned platform version (defaults to the current release channel)."
20646
21161
  });
20647
- contentDir = Option30.String("--content-dir", {
21162
+ contentDir = Option32.String("--content-dir", {
20648
21163
  description: "Path to a local m8t repo checkout (skips the tarball tree-SHA fetch)."
20649
21164
  });
20650
- manifestUrl = Option30.String("--manifest-url", {
21165
+ manifestUrl = Option32.String("--manifest-url", {
20651
21166
  description: "Fetch the release manifest from this URL instead of the release channel."
20652
21167
  });
20653
- manifestFile = Option30.String("--manifest-file", {
21168
+ manifestFile = Option32.String("--manifest-file", {
20654
21169
  description: "Read the release manifest from this local file instead of the release channel."
20655
21170
  });
20656
- verify = Option30.Boolean("--verify", false, {
21171
+ verify = Option32.Boolean("--verify", false, {
20657
21172
  description: "Additionally probe the live gateway (image tag + /api/version) and report stamp-vs-live."
20658
21173
  });
20659
- output = Option30.String("--output");
21174
+ output = Option32.String("--output");
20660
21175
  async executeCommand() {
20661
21176
  const mode = resolveOutputMode(
20662
21177
  this.output,
@@ -20769,12 +21284,12 @@ var PlatformStatusCommand = class extends M8tCommand {
20769
21284
  };
20770
21285
 
20771
21286
  // src/commands/platform/update.ts
20772
- import { Command as Command33, Option as Option31 } from "clipanion";
21287
+ import { Command as Command35, Option as Option33 } from "clipanion";
20773
21288
  import { confirm as confirm5 } from "@inquirer/prompts";
20774
21289
  import { DefaultAzureCredential as DefaultAzureCredential17 } from "@azure/identity";
20775
21290
 
20776
21291
  // src/lib/platform-converge-cli.ts
20777
- import * as path26 from "path";
21292
+ import * as path31 from "path";
20778
21293
 
20779
21294
  // src/lib/platform-infra-params.ts
20780
21295
  import { TableClient as TableClient3 } from "@azure/data-tables";
@@ -20859,17 +21374,18 @@ init_errors();
20859
21374
 
20860
21375
  // src/lib/seed-refresh-driver.ts
20861
21376
  init_esm2();
20862
- import * as path25 from "path";
21377
+ import * as fs29 from "fs";
21378
+ import * as path30 from "path";
20863
21379
 
20864
21380
  // src/lib/seed-refresh.ts
20865
21381
  init_errors();
20866
- import * as fs24 from "fs";
20867
- import * as path24 from "path";
21382
+ import * as fs28 from "fs";
21383
+ import * as path29 from "path";
20868
21384
 
20869
21385
  // src/lib/seed-merge.ts
20870
- import * as fs23 from "fs";
20871
- import * as os10 from "os";
20872
- import * as path23 from "path";
21386
+ import * as fs27 from "fs";
21387
+ import * as os11 from "os";
21388
+ import * as path28 from "path";
20873
21389
  import { spawnSync as spawnSync3 } from "child_process";
20874
21390
  function isProbablyText(s) {
20875
21391
  return !s.includes("\0");
@@ -20879,14 +21395,14 @@ function mergeThreeWay(ours, base, theirs) {
20879
21395
  return { ok: false, merged: "" };
20880
21396
  }
20881
21397
  const lf = (s) => s.replace(/\r\n/g, "\n");
20882
- const dir = fs23.mkdtempSync(path23.join(os10.tmpdir(), "seed-merge-"));
21398
+ const dir = fs27.mkdtempSync(path28.join(os11.tmpdir(), "seed-merge-"));
20883
21399
  try {
20884
- const o = path23.join(dir, "ours");
20885
- const b = path23.join(dir, "base");
20886
- const t = path23.join(dir, "theirs");
20887
- fs23.writeFileSync(o, lf(ours));
20888
- fs23.writeFileSync(b, lf(base));
20889
- fs23.writeFileSync(t, lf(theirs));
21400
+ const o = path28.join(dir, "ours");
21401
+ const b = path28.join(dir, "base");
21402
+ const t = path28.join(dir, "theirs");
21403
+ fs27.writeFileSync(o, lf(ours));
21404
+ fs27.writeFileSync(b, lf(base));
21405
+ fs27.writeFileSync(t, lf(theirs));
20890
21406
  const res = spawnSync3(
20891
21407
  "git",
20892
21408
  ["merge-file", "-p", "--diff3", o, b, t],
@@ -20900,28 +21416,28 @@ function mergeThreeWay(ours, base, theirs) {
20900
21416
  }
20901
21417
  return { ok: false, merged: "" };
20902
21418
  } finally {
20903
- fs23.rmSync(dir, { recursive: true, force: true });
21419
+ fs27.rmSync(dir, { recursive: true, force: true });
20904
21420
  }
20905
21421
  }
20906
- var skip = (path43, skipReason) => ({ path: path43, kind: "skip", skipReason });
21422
+ var skip = (path48, skipReason) => ({ path: path48, kind: "skip", skipReason });
20907
21423
  function classifyCandidate(c) {
20908
- const { path: path43, base, ours, theirs } = c;
20909
- if (theirs === base) return { path: path43, kind: "noop" };
21424
+ const { path: path48, base, ours, theirs } = c;
21425
+ if (theirs === base) return { path: path48, kind: "noop" };
20910
21426
  if (base === null) {
20911
- if (theirs === null) return { path: path43, kind: "noop" };
20912
- if (ours === null) return { path: path43, kind: "add", content: theirs };
20913
- if (ours === theirs) return { path: path43, kind: "noop" };
20914
- return skip(path43, "you already have a file at this path");
21427
+ if (theirs === null) return { path: path48, kind: "noop" };
21428
+ if (ours === null) return { path: path48, kind: "add", content: theirs };
21429
+ if (ours === theirs) return { path: path48, kind: "noop" };
21430
+ return skip(path48, "you already have a file at this path");
20915
21431
  }
20916
21432
  if (ours === null) {
20917
- return theirs === null ? { path: path43, kind: "noop" } : skip(path43, "you removed this file; upstream changed it");
21433
+ return theirs === null ? { path: path48, kind: "noop" } : skip(path48, "you removed this file; upstream changed it");
20918
21434
  }
20919
21435
  if (theirs === null) {
20920
- return ours === base ? { path: path43, kind: "delete" } : skip(path43, "you edited this file; upstream removed it");
21436
+ return ours === base ? { path: path48, kind: "delete" } : skip(path48, "you edited this file; upstream removed it");
20921
21437
  }
20922
- if (ours === base) return { path: path43, kind: "update", content: theirs };
21438
+ if (ours === base) return { path: path48, kind: "update", content: theirs };
20923
21439
  const m = mergeThreeWay(ours, base, theirs);
20924
- return m.ok ? { path: path43, kind: "update", content: m.merged } : skip(path43, "your edits conflict with the update");
21440
+ return m.ok ? { path: path48, kind: "update", content: m.merged } : skip(path48, "your edits conflict with the update");
20925
21441
  }
20926
21442
 
20927
21443
  // src/lib/seed-pr-body.ts
@@ -20956,8 +21472,8 @@ function composeSeedPrBody(s) {
20956
21472
  // src/lib/seed-refresh.ts
20957
21473
  function readIf(dir, rel) {
20958
21474
  if (!dir) return null;
20959
- const abs = path24.join(dir, rel);
20960
- return fs24.existsSync(abs) ? fs24.readFileSync(abs, "utf8") : null;
21475
+ const abs = path29.join(dir, rel);
21476
+ return fs28.existsSync(abs) ? fs28.readFileSync(abs, "utf8") : null;
20961
21477
  }
20962
21478
  async function assembleCandidates(args) {
20963
21479
  const paths = /* @__PURE__ */ new Set([...args.lineage?.ownedPaths ?? [], ...args.trees.ownedAtTheirs]);
@@ -21089,7 +21605,8 @@ function dedupeBrainRepos(agents) {
21089
21605
  function seedContentDir(contentRoot, manifest, seedName) {
21090
21606
  const items = manifest.components.brainSeeds.items;
21091
21607
  if (!Object.hasOwn(items, seedName)) return null;
21092
- return path25.join(contentRoot, items[seedName].path);
21608
+ const dir = path30.join(contentRoot, items[seedName].path);
21609
+ return fs29.existsSync(dir) ? dir : null;
21093
21610
  }
21094
21611
  function bindRepoApi(token, repo) {
21095
21612
  return {
@@ -21106,12 +21623,12 @@ function bindRepoApi(token, repo) {
21106
21623
  openPr: (head, base, title, body) => openPullRequestViaApp({ token, repo, base, head, title, body }),
21107
21624
  updatePr: (n, title, body) => updatePullRequestViaApp({ token, repo, number: n, title, body }),
21108
21625
  closePr: (n, comment) => closePullRequestViaApp({ token, repo, number: n, comment }),
21109
- readFileAtRef: (path43, ref) => readRepoFileViaApp({ token, repo, path: path43, ref })
21626
+ readFileAtRef: (path48, ref) => readRepoFileViaApp({ token, repo, path: path48, ref })
21110
21627
  };
21111
21628
  }
21112
21629
  async function runSeedRefresh(args) {
21113
21630
  const targetCommit = args.manifest.platform.commit;
21114
- const theirsRoot = await resolveReleaseContent(args.manifest, {});
21631
+ const theirsRoot = await resolveReleaseContentWithAgents(args.manifest, {});
21115
21632
  const repos = dedupeBrainRepos(args.agents);
21116
21633
  const results = [];
21117
21634
  let delivered = 0;
@@ -21148,6 +21665,7 @@ async function runSeedRefresh(args) {
21148
21665
  const advisorLabel = ADVISOR_LABEL[seedName] ?? seedName;
21149
21666
  let lineage = marker?.seeds.find((s) => s.name === seedName) ?? null;
21150
21667
  let baseDir = null;
21668
+ const agentSourced = Boolean(args.manifest.components.agents && Object.values(args.manifest.components.agents).some((a) => a.persona === seedName));
21151
21669
  if (lineage) {
21152
21670
  try {
21153
21671
  const baseRoot = await resolveReleaseContent(
@@ -21175,6 +21693,11 @@ async function runSeedRefresh(args) {
21175
21693
  }
21176
21694
  }
21177
21695
  }
21696
+ if (agentSourced && !baseDir) {
21697
+ args.onWarn?.(
21698
+ `${ref.repo}: seed '${seedName}' comes from an agent repo and no merge base could be resolved \u2014 new files are delivered, files you already have are skipped and never overwritten.`
21699
+ );
21700
+ }
21178
21701
  const trees = { baseDir, theirsDir, ownedAtTheirs: deriveOwnedPaths(theirsDir) };
21179
21702
  const source = { readOurs: (p) => readRepoFileViaApp({ token, repo: ref.repo, path: p }) };
21180
21703
  const res = await refreshBrainRepo({
@@ -21219,7 +21742,7 @@ async function buildConvergeDeps(args) {
21219
21742
  const persona = a.metadata.persona;
21220
21743
  if (persona) discovered[persona] = a.name;
21221
21744
  }
21222
- const loaderPath = path26.join(args.contentDir, "targets/foundry/brain-loader.md");
21745
+ const loaderPath = path31.join(args.contentDir, "targets/foundry/brain-loader.md");
21223
21746
  return {
21224
21747
  async applyPersona(a, ctx) {
21225
21748
  const personaName = a.personaName;
@@ -21235,7 +21758,7 @@ async function buildConvergeDeps(args) {
21235
21758
  return applyPersona(a, ctx, {
21236
21759
  agentName,
21237
21760
  project: args.project,
21238
- personaDir: path26.join(ctx.contentDir, personaItem.path),
21761
+ personaDir: path31.join(ctx.contentDir, personaItem.path),
21239
21762
  loaderPath
21240
21763
  });
21241
21764
  },
@@ -21417,40 +21940,40 @@ function assertCliVersionOk(manifest, runningVersion, onWarn = () => {
21417
21940
  // src/commands/platform/update.ts
21418
21941
  var PlatformUpdateCommand = class extends M8tCommand {
21419
21942
  static paths = [["platform", "update"]];
21420
- static usage = Command33.Usage({
21943
+ static usage = Command35.Usage({
21421
21944
  description: "Converge the whole platform (gateway, hosted agents, personas, infra) to a release manifest.",
21422
21945
  details: "Fetches a release manifest (the current channel by default), diffs it against the installed-state stamp, and converges each changed component via its own executor: rolls the gateway/hosted-agent images, re-versions prompt personas (compose-preserving), and records infra state. A deploy/ tree drift is reported but NOT applied unless --force-infra is passed. Use --check to preview, --only to converge a single component, --yes to skip the confirmation prompt."
21423
21946
  });
21424
- subscription = Option31.String("--subscription");
21425
- resourceGroup = Option31.String("--resource-group", {
21947
+ subscription = Option33.String("--subscription");
21948
+ resourceGroup = Option33.String("--resource-group", {
21426
21949
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
21427
21950
  });
21428
- to = Option31.String("--to", {
21951
+ to = Option33.String("--to", {
21429
21952
  description: "Pin the platform version to converge to (defaults to the current release channel)."
21430
21953
  });
21431
- only = Option31.String("--only", {
21954
+ only = Option33.String("--only", {
21432
21955
  description: "Converge only one component: infra | gateway | codingAgent | azureExecutor | personas | brainSeeds."
21433
21956
  });
21434
- check = Option31.Boolean("--check", false);
21435
- yes = Option31.Boolean("--yes", false);
21436
- skipInfra = Option31.Boolean("--skip-infra", false);
21437
- forceInfra = Option31.Boolean("--force-infra", false);
21438
- suffix = Option31.String("--suffix", {
21957
+ check = Option33.Boolean("--check", false);
21958
+ yes = Option33.Boolean("--yes", false);
21959
+ skipInfra = Option33.Boolean("--skip-infra", false);
21960
+ forceInfra = Option33.Boolean("--force-infra", false);
21961
+ suffix = Option33.String("--suffix", {
21439
21962
  description: "Required with --force-infra \u2014 the existing deployment's resource-name suffix (avoids provisioning duplicates)."
21440
21963
  });
21441
- contentDir = Option31.String("--content-dir", {
21964
+ contentDir = Option33.String("--content-dir", {
21442
21965
  description: "Path to a local m8t repo checkout (skips the tarball fetch + tree-drift check)."
21443
21966
  });
21444
- manifestUrl = Option31.String("--manifest-url", {
21967
+ manifestUrl = Option33.String("--manifest-url", {
21445
21968
  description: "Fetch the release manifest from this URL instead of the release channel."
21446
21969
  });
21447
- manifestFile = Option31.String("--manifest-file", {
21970
+ manifestFile = Option33.String("--manifest-file", {
21448
21971
  description: "Read the release manifest from this local file instead of the release channel."
21449
21972
  });
21450
- endpoint = Option31.String("--endpoint", {
21973
+ endpoint = Option33.String("--endpoint", {
21451
21974
  description: "Foundry project endpoint URL. Disambiguates the project in a multi-project subscription."
21452
21975
  });
21453
- output = Option31.String("--output");
21976
+ output = Option33.String("--output");
21454
21977
  async executeCommand() {
21455
21978
  const mode = resolveOutputMode(
21456
21979
  this.output,
@@ -21494,7 +22017,7 @@ var PlatformUpdateCommand = class extends M8tCommand {
21494
22017
  assertCliVersionOk(manifest, CLI_VERSION, onWarn);
21495
22018
  const stamp = await readStamp({ credential: credential2, subscriptionId, resourceGroup });
21496
22019
  onProgress("resolving release content\u2026");
21497
- const contentDir = await resolveReleaseContent(manifest, { contentDir: contentDirFlag });
22020
+ const contentDir = await resolveReleaseContentWithAgents(manifest, { contentDir: contentDirFlag });
21498
22021
  const tree = contentDirFlag ? { treeShaOf: () => void 0 } : await fetchRepoTree(manifest.platform.commit);
21499
22022
  if (!contentDirFlag) {
21500
22023
  const mismatches = verifyPersonaTrees(manifest, tree);
@@ -21578,7 +22101,7 @@ var PlatformUpdateCommand = class extends M8tCommand {
21578
22101
  };
21579
22102
 
21580
22103
  // src/commands/platform/converge.ts
21581
- import { Command as Command34 } from "clipanion";
22104
+ import { Command as Command36 } from "clipanion";
21582
22105
 
21583
22106
  // src/lib/platform-converge-mi.ts
21584
22107
  import { ManagedIdentityCredential } from "@azure/identity";
@@ -21669,15 +22192,15 @@ async function patchApplyRequest(client, mutate) {
21669
22192
  }
21670
22193
 
21671
22194
  // src/lib/platform-self-update.ts
21672
- import * as fs25 from "fs";
21673
- import * as path27 from "path";
22195
+ import * as fs30 from "fs";
22196
+ import * as path32 from "path";
21674
22197
  function toVTag2(v) {
21675
22198
  return v.startsWith("v") ? v : `v${v}`;
21676
22199
  }
21677
22200
  function readBakedReleaseVersion(repoRoot) {
21678
22201
  if (!repoRoot) return null;
21679
22202
  try {
21680
- const raw = fs25.readFileSync(path27.join(repoRoot, "installer", "version.json"), "utf8");
22203
+ const raw = fs30.readFileSync(path32.join(repoRoot, "installer", "version.json"), "utf8");
21681
22204
  const v = JSON.parse(raw).version;
21682
22205
  return typeof v === "string" && v.length > 0 ? v : null;
21683
22206
  } catch {
@@ -21882,7 +22405,7 @@ async function failIfStillInFlight(client, now, error) {
21882
22405
  }
21883
22406
  var PlatformConvergeCommand = class extends M8tCommand {
21884
22407
  static paths = [["platform", "converge"]];
21885
- static usage = Command34.Usage({
22408
+ static usage = Command36.Usage({
21886
22409
  category: "Platform",
21887
22410
  description: "Headless updater-job driver: claim a pending apply-request and converge the platform to it.",
21888
22411
  details: "The Managed-Identity-authenticated entry point run by the updater Container Apps job. One invocation is one tick: it claims the pending apply-request row (if any), refuses a downgrade against the installed stamp, self-fetches and validates the target manifest, self-updates its own engine image when the manifest requires a newer CLI, then drives the converge engine behind the health-gate + auto-rollback. Reads its subscription/RG/endpoint/channel from env (MI_CLIENT_ID, SUBSCRIPTION_ID, RESOURCE_GROUP, FOUNDRY_ENDPOINT, M8T_UPDATE_CHANNEL_URL). Not intended for interactive use \u2014 the founder-facing path is 'm8t platform update'."
@@ -21964,7 +22487,7 @@ var PlatformConvergeCommand = class extends M8tCommand {
21964
22487
  interactive: false,
21965
22488
  endpoint: ctx.endpoint
21966
22489
  });
21967
- const contentDir = await resolveReleaseContent(manifest, repoRoot ? { contentDir: repoRoot } : {});
22490
+ const contentDir = await resolveReleaseContentWithAgents(manifest, repoRoot ? { contentDir: repoRoot } : {});
21968
22491
  const tree = manifest.components.infra?.treeSha ? { treeShaOf: () => void 0 } : await fetchRepoTree(manifest.platform.commit);
21969
22492
  const suffix = await this.recoverSuffix(ctx);
21970
22493
  const gatewayResourceId = await this.resolveGatewayResourceId(ctx, suffix);
@@ -22097,8 +22620,8 @@ function targetManifestSource(ctx, target) {
22097
22620
  }
22098
22621
 
22099
22622
  // src/commands/platform/seed-stamp.ts
22100
- import { readFileSync as readFileSync18 } from "fs";
22101
- import { Command as Command35, Option as Option32 } from "clipanion";
22623
+ import { readFileSync as readFileSync21 } from "fs";
22624
+ import { Command as Command37, Option as Option34 } from "clipanion";
22102
22625
  import { DefaultAzureCredential as DefaultAzureCredential18, ManagedIdentityCredential as ManagedIdentityCredential2 } from "@azure/identity";
22103
22626
  init_errors();
22104
22627
 
@@ -22184,7 +22707,7 @@ function buildSeedStamp(d, cliVersion, nowIso) {
22184
22707
 
22185
22708
  // src/commands/platform/seed-stamp.ts
22186
22709
  async function seedStamp2(args) {
22187
- const readFileImpl = args.readFileImpl ?? ((p) => readFileSync18(p, "utf8"));
22710
+ const readFileImpl = args.readFileImpl ?? ((p) => readFileSync21(p, "utf8"));
22188
22711
  const readStampImpl = args.readStampImpl ?? readStamp;
22189
22712
  const writeStampImpl = args.writeStampImpl ?? ((stamp2, o) => writeStamp({ ...o, stamp: stamp2 }));
22190
22713
  const discoverImpl = args.discoverImpl ?? discoverStampStorage;
@@ -22230,15 +22753,15 @@ async function seedStamp2(args) {
22230
22753
  }
22231
22754
  var PlatformSeedStampCommand = class extends M8tCommand {
22232
22755
  static paths = [["platform", "seed-stamp"]];
22233
- static usage = Command35.Usage({
22756
+ static usage = Command37.Usage({
22234
22757
  description: "INTERNAL: write the initial installed-state stamp from a build-time install descriptor.",
22235
22758
  details: "Used by the cloud installer at the end of a from-zero install so the platform records which release it is running. Writes the stamp ONLY IF ABSENT \u2014 it never overwrites a stamp written by the converge engine, so a re-run or a container restart is harmless. Not a founder-facing command: to change what is installed, use 'm8t platform update'."
22236
22759
  });
22237
- descriptor = Option32.String("--descriptor", { description: "Path to install-descriptor.json (baked into the installer image)." });
22238
- subscription = Option32.String("--subscription");
22239
- resourceGroup = Option32.String("--resource-group");
22240
- miClientId = Option32.String("--mi-client-id", { description: "Authenticate as this user-assigned managed identity instead of the ambient credential." });
22241
- output = Option32.String("--output");
22760
+ descriptor = Option34.String("--descriptor", { description: "Path to install-descriptor.json (baked into the installer image)." });
22761
+ subscription = Option34.String("--subscription");
22762
+ resourceGroup = Option34.String("--resource-group");
22763
+ miClientId = Option34.String("--mi-client-id", { description: "Authenticate as this user-assigned managed identity instead of the ambient credential." });
22764
+ output = Option34.String("--output");
22242
22765
  async executeCommand() {
22243
22766
  const mode = resolveOutputMode(this.output, this.context.stdout);
22244
22767
  const need = (v, flag) => {
@@ -22270,7 +22793,7 @@ var PlatformSeedStampCommand = class extends M8tCommand {
22270
22793
  };
22271
22794
 
22272
22795
  // src/commands/platform/stamp-build.ts
22273
- import { Command as Command36, Option as Option33 } from "clipanion";
22796
+ import { Command as Command38, Option as Option35 } from "clipanion";
22274
22797
  import { DefaultAzureCredential as DefaultAzureCredential19, ManagedIdentityCredential as ManagedIdentityCredential3 } from "@azure/identity";
22275
22798
  init_errors();
22276
22799
 
@@ -22304,17 +22827,17 @@ function buildRunningBuildStamp(input) {
22304
22827
  // src/commands/platform/stamp-build.ts
22305
22828
  var PlatformStampBuildCommand = class extends M8tCommand {
22306
22829
  static paths = [["platform", "stamp-build"]];
22307
- static usage = Command36.Usage({
22830
+ static usage = Command38.Usage({
22308
22831
  description: "Record the currently running build as this install's platform version.",
22309
22832
  details: "For installs that are deployed continuously rather than from a published release. Unlike the install-time record, this overwrites on every run \u2014 the running build is the truth. Only components this writer deploys are reported; the rest are marked as managed elsewhere."
22310
22833
  });
22311
- version = Option33.String("--version", { description: "The running build's own version, bare X.Y.Z." });
22312
- gatewayTag = Option33.String("--gateway-tag", { description: "The tag of the gateway image this build deployed." });
22313
- gatewayDigest = Option33.String("--gateway-digest", { description: "The digest of the gateway image this build deployed." });
22314
- subscription = Option33.String("--subscription");
22315
- resourceGroup = Option33.String("--resource-group");
22316
- miClientId = Option33.String("--mi-client-id", { description: "Authenticate as this user-assigned managed identity instead of the ambient credential." });
22317
- output = Option33.String("--output");
22834
+ version = Option35.String("--version", { description: "The running build's own version, bare X.Y.Z." });
22835
+ gatewayTag = Option35.String("--gateway-tag", { description: "The tag of the gateway image this build deployed." });
22836
+ gatewayDigest = Option35.String("--gateway-digest", { description: "The digest of the gateway image this build deployed." });
22837
+ subscription = Option35.String("--subscription");
22838
+ resourceGroup = Option35.String("--resource-group");
22839
+ miClientId = Option35.String("--mi-client-id", { description: "Authenticate as this user-assigned managed identity instead of the ambient credential." });
22840
+ output = Option35.String("--output");
22318
22841
  async executeCommand() {
22319
22842
  const mode = resolveOutputMode(this.output, this.context.stdout);
22320
22843
  const need = (v, flag) => {
@@ -22366,7 +22889,7 @@ var PlatformStampBuildCommand = class extends M8tCommand {
22366
22889
  };
22367
22890
 
22368
22891
  // src/commands/platform/policy.ts
22369
- import { Command as Command37, Option as Option34 } from "clipanion";
22892
+ import { Command as Command39, Option as Option36 } from "clipanion";
22370
22893
  import { DefaultAzureCredential as DefaultAzureCredential20, ManagedIdentityCredential as ManagedIdentityCredential4 } from "@azure/identity";
22371
22894
  init_errors();
22372
22895
 
@@ -22422,16 +22945,16 @@ async function readPolicy(opts) {
22422
22945
  // src/commands/platform/policy.ts
22423
22946
  var PlatformPolicyCommand = class extends M8tCommand {
22424
22947
  static paths = [["platform", "policy"]];
22425
- static usage = Command37.Usage({
22948
+ static usage = Command39.Usage({
22426
22949
  description: "Show or set how this install handles available platform updates.",
22427
22950
  details: "Modes: 'notify-only' shows updates but never applies them; 'auto-critical' (the default when unset) applies critical releases without asking; 'auto-all' applies every release. Use 'notify-only' where something else already controls what is deployed.",
22428
22951
  examples: [["Show the current mode", "m8t platform policy"], ["Never apply automatically", "m8t platform policy --set notify-only"]]
22429
22952
  });
22430
- set = Option34.String("--set", { description: "notify-only | auto-critical | auto-all" });
22431
- subscription = Option34.String("--subscription");
22432
- resourceGroup = Option34.String("--resource-group");
22433
- miClientId = Option34.String("--mi-client-id");
22434
- output = Option34.String("--output");
22953
+ set = Option36.String("--set", { description: "notify-only | auto-critical | auto-all" });
22954
+ subscription = Option36.String("--subscription");
22955
+ resourceGroup = Option36.String("--resource-group");
22956
+ miClientId = Option36.String("--mi-client-id");
22957
+ output = Option36.String("--output");
22435
22958
  async executeCommand() {
22436
22959
  const mode = resolveOutputMode(this.output, this.context.stdout);
22437
22960
  const need = (v, flag) => {
@@ -22477,7 +23000,7 @@ var PlatformPolicyCommand = class extends M8tCommand {
22477
23000
  };
22478
23001
 
22479
23002
  // src/commands/platform/enable-cost-report.ts
22480
- import { Command as Command38, Option as Option35 } from "clipanion";
23003
+ import { Command as Command40, Option as Option37 } from "clipanion";
22481
23004
 
22482
23005
  // src/lib/wire-gateway-acs.ts
22483
23006
  init_rbac();
@@ -22517,18 +23040,18 @@ async function wireGatewayForAcs(args) {
22517
23040
  init_errors();
22518
23041
  var PlatformEnableCostReportCommand = class extends M8tCommand {
22519
23042
  static paths = [["platform", "enable-cost-report"]];
22520
- static usage = Command38.Usage({
23043
+ static usage = Command40.Usage({
22521
23044
  description: "Wire the deployed gateway to send the bi-weekly cost report via ACS Email.",
22522
23045
  details: "Discovers the live gateway Container App, grants its managed identity Contributor at the ACS resource scope (authorising the ACS Email send), and sets M8T_ACS_ENDPOINT / M8T_ACS_SENDER / M8T_ENABLE_COST_REPORTER=1 on the gateway. Idempotent \u2014 safely re-runnable. ACS is created during the executor deploy; pass its endpoint, sender, and resource id (from that deploy or 'az communication list')."
22523
23046
  });
22524
- subscription = Option35.String("--subscription");
22525
- resourceGroup = Option35.String("--resource-group", {
23047
+ subscription = Option37.String("--subscription");
23048
+ resourceGroup = Option37.String("--resource-group", {
22526
23049
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
22527
23050
  });
22528
- acsEndpoint = Option35.String("--acs-endpoint", { required: true, description: "ACS data-plane endpoint, e.g. https://acs-<name>.communication.azure.com/" });
22529
- acsSender = Option35.String("--acs-sender", { required: true, description: "Managed-domain sender address, e.g. DoNotReply@<guid>.azurecomm.net" });
22530
- acsResourceId = Option35.String("--acs-resource-id", { required: true, description: "ARM resource id of the acs-<name> Communication Service \u2014 the role-grant scope." });
22531
- output = Option35.String("--output");
23051
+ acsEndpoint = Option37.String("--acs-endpoint", { required: true, description: "ACS data-plane endpoint, e.g. https://acs-<name>.communication.azure.com/" });
23052
+ acsSender = Option37.String("--acs-sender", { required: true, description: "Managed-domain sender address, e.g. DoNotReply@<guid>.azurecomm.net" });
23053
+ acsResourceId = Option37.String("--acs-resource-id", { required: true, description: "ARM resource id of the acs-<name> Communication Service \u2014 the role-grant scope." });
23054
+ output = Option37.String("--output");
22532
23055
  async executeCommand() {
22533
23056
  const mode = resolveOutputMode(
22534
23057
  this.output,
@@ -22602,45 +23125,45 @@ var PlatformEnableCostReportCommand = class extends M8tCommand {
22602
23125
  };
22603
23126
 
22604
23127
  // src/commands/platform/enable-auto-update.ts
22605
- import { Command as Command39, Option as Option36 } from "clipanion";
23128
+ import { Command as Command41, Option as Option38 } from "clipanion";
22606
23129
  import { confirm as confirm6 } from "@inquirer/prompts";
22607
23130
  import { DefaultAzureCredential as DefaultAzureCredential21 } from "@azure/identity";
22608
23131
  init_errors();
22609
23132
  var PlatformEnableAutoUpdateCommand = class extends M8tCommand {
22610
23133
  static paths = [["platform", "enable-auto-update"]];
22611
- static usage = Command39.Usage({
23134
+ static usage = Command41.Usage({
22612
23135
  category: "Platform",
22613
23136
  description: "Retrofit the auto-updater (MI + cron job + role assignments) onto an existing install.",
22614
23137
  details: "For an install that predates the Platform Update Framework: recovers the deployment's resource-name suffix (from the stamped system/infra-params row, or by verified derivation from the live gateway), recovers the other bicep params from live state (WITHOUT changing the deployed gateway image), and re-runs deploy/main.bicep with provisionUpdater=true \u2014 which provisions the updater managed identity, the cron Container Apps Job, and every role assignment (Owner@RG + Foundry User@account + Storage Table + Storage Blob + AcrPull), all scoped to the resource group. On success, backfills system/infra-params so future converges never have to re-derive the suffix. Idempotent \u2014 safe to re-run."
22615
23138
  });
22616
- subscription = Option36.String("--subscription");
22617
- resourceGroup = Option36.String("--resource-group", {
23139
+ subscription = Option38.String("--subscription");
23140
+ resourceGroup = Option38.String("--resource-group", {
22618
23141
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
22619
23142
  });
22620
- suffix = Option36.String("--suffix", {
23143
+ suffix = Option38.String("--suffix", {
22621
23144
  description: "The existing deployment's resource-name suffix. Required when it cannot be recovered from system/infra-params or the live gateway."
22622
23145
  });
22623
- installerImage = Option36.String("--installer-image", {
23146
+ installerImage = Option38.String("--installer-image", {
22624
23147
  required: true,
22625
23148
  description: "Updater CA-Job image ref (the converge engine at the current release). Required \u2014 an empty image would skip provisioning."
22626
23149
  });
22627
- updateCron = Option36.String("--update-cron", {
23150
+ updateCron = Option38.String("--update-cron", {
22628
23151
  description: "Cron schedule for the updater job (bicep default applies when omitted)."
22629
23152
  });
22630
- channelUrl = Option36.String("--channel-url", {
23153
+ channelUrl = Option38.String("--channel-url", {
22631
23154
  description: "Release-channel URL the updater job polls (bicep default applies when omitted)."
22632
23155
  });
22633
- location = Option36.String("--location", {
23156
+ location = Option38.String("--location", {
22634
23157
  description: "Region for the updater identity + job. Defaults to the resource group's existing resources."
22635
23158
  });
22636
- foundryTracing = Option36.String("--foundry-tracing", {
23159
+ foundryTracing = Option38.String("--foundry-tracing", {
22637
23160
  description: "project | account | skip. Pass the value the install was deployed with \u2014 omitting it lets the bicep default (project) switch tracing on."
22638
23161
  });
22639
- endpoint = Option36.String("--endpoint", {
23162
+ endpoint = Option38.String("--endpoint", {
22640
23163
  description: "Foundry project endpoint URL. Disambiguates the project in a multi-project subscription."
22641
23164
  });
22642
- yes = Option36.Boolean("--yes", false);
22643
- output = Option36.String("--output");
23165
+ yes = Option38.Boolean("--yes", false);
23166
+ output = Option38.String("--output");
22644
23167
  async executeCommand() {
22645
23168
  const mode = resolveOutputMode(
22646
23169
  this.output,
@@ -22777,7 +23300,7 @@ var PlatformEnableAutoUpdateCommand = class extends M8tCommand {
22777
23300
  };
22778
23301
 
22779
23302
  // src/commands/deploy.ts
22780
- import { Command as Command40, Option as Option37 } from "clipanion";
23303
+ import { Command as Command42, Option as Option39 } from "clipanion";
22781
23304
 
22782
23305
  // src/lib/app-reg.ts
22783
23306
  init_errors();
@@ -23062,7 +23585,7 @@ async function patchRedirectUris(appObjectId, fqdn) {
23062
23585
  init_errors();
23063
23586
 
23064
23587
  // src/lib/whatif.ts
23065
- import * as path28 from "path";
23588
+ import * as path33 from "path";
23066
23589
 
23067
23590
  // src/lib/identifier-patterns.ts
23068
23591
  var IDENTIFIER_PATTERNS = [
@@ -23118,7 +23641,7 @@ function deriveResourceType(resourceId) {
23118
23641
  return parts.join("/");
23119
23642
  }
23120
23643
  async function runWhatIf(opts) {
23121
- const bicepPath = path28.join(opts.repoRoot, "deploy", "main.bicep");
23644
+ const bicepPath = path33.join(opts.repoRoot, "deploy", "main.bicep");
23122
23645
  const out = await runAz([
23123
23646
  "deployment",
23124
23647
  "group",
@@ -23216,9 +23739,9 @@ function flattenDelta(delta, prefix = "") {
23216
23739
  const out = [];
23217
23740
  for (const d of delta) {
23218
23741
  const segment = /^[0-9]+$/.test(d.path) ? `[${d.path}]` : prefix ? `.${d.path}` : d.path;
23219
- const path43 = prefix ? `${prefix}${segment}` : d.path;
23220
- if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children, path43));
23221
- else out.push({ ...d, path: path43 });
23742
+ const path48 = prefix ? `${prefix}${segment}` : d.path;
23743
+ if (d.children && d.children.length > 0) out.push(...flattenDelta(d.children, path48));
23744
+ else out.push({ ...d, path: path48 });
23222
23745
  }
23223
23746
  return out;
23224
23747
  }
@@ -23268,52 +23791,52 @@ function classifyWhatIf(changes) {
23268
23791
  var DEFAULT_IMAGE_REF = "ghcr.io/m8t-labs/m8t:latest";
23269
23792
  var DeployCommand = class extends M8tCommand {
23270
23793
  static paths = [["deploy"]];
23271
- static usage = Command40.Usage({
23794
+ static usage = Command42.Usage({
23272
23795
  description: "Deploy (or update) the m8t gateway/webapp stack via Bicep.",
23273
23796
  details: "Ensures the Entra app reg (or pass --client-id to reuse an existing one \u2014 required if you can't create app regs), writes ~/.m8t/config.yaml, ensures the resource group, and runs deploy/main.bicep. The repo is located via ~/.m8t/repo-root."
23274
23797
  });
23275
- subscription = Option37.String("--subscription");
23276
- resourceGroup = Option37.String("--resource-group", "rg-m8t-stack");
23277
- location = Option37.String("--location", "eastus");
23278
- suffix = Option37.String("--suffix", "");
23279
- imageRef = Option37.String("--image-ref", DEFAULT_IMAGE_REF);
23280
- acrPullIdentity = Option37.String("--acrpull-identity");
23281
- acrResourceId = Option37.String("--acr-resource-id");
23282
- foundryEndpoint = Option37.String("--foundry-endpoint");
23283
- foundryResourceId = Option37.String("--foundry-resource-id");
23284
- foundryTracing = Option37.String("--foundry-tracing");
23798
+ subscription = Option39.String("--subscription");
23799
+ resourceGroup = Option39.String("--resource-group", "rg-m8t-stack");
23800
+ location = Option39.String("--location", "eastus");
23801
+ suffix = Option39.String("--suffix", "");
23802
+ imageRef = Option39.String("--image-ref", DEFAULT_IMAGE_REF);
23803
+ acrPullIdentity = Option39.String("--acrpull-identity");
23804
+ acrResourceId = Option39.String("--acr-resource-id");
23805
+ foundryEndpoint = Option39.String("--foundry-endpoint");
23806
+ foundryResourceId = Option39.String("--foundry-resource-id");
23807
+ foundryTracing = Option39.String("--foundry-tracing");
23285
23808
  // project | account | skip (bicep default: project)
23286
- clientId = Option37.String("--client-id");
23287
- whatIf = Option37.Boolean("--what-if", false);
23809
+ clientId = Option39.String("--client-id");
23810
+ whatIf = Option39.Boolean("--what-if", false);
23288
23811
  // Only meaningful with --what-if. Routes the comparison through the
23289
23812
  // value-free renderers (see ./lib/whatif-redact.js) instead of the default
23290
23813
  // before/after renderer. Defaults false so a local, interactive run keeps
23291
23814
  // showing values — that is the whole diagnostic point of --what-if.
23292
23815
  // Automation that forwards this output anywhere non-private (a CI log, an
23293
23816
  // issue) MUST pass --redact.
23294
- redact = Option37.Boolean("--redact", false);
23295
- output = Option37.String("--output");
23817
+ redact = Option39.Boolean("--redact", false);
23818
+ output = Option39.String("--output");
23296
23819
  // Subscription-scoped role assignments. Omitted ⇒ the template default (true).
23297
23820
  // Pass false when deploying as a principal scoped to the resource group only:
23298
23821
  // it cannot deploy at subscription scope, and those assignments persist
23299
23822
  // idempotently from the initial deployment anyway.
23300
- assignSubscriptionRoles = Option37.String("--assign-subscription-roles");
23823
+ assignSubscriptionRoles = Option39.String("--assign-subscription-roles");
23301
23824
  // Referee — all optional, undefined by default ⇒ the bicep defaults
23302
23825
  // apply (dormant: gatewayCpu=0.25, gatewayMemory=0.5Gi, every referee/exam var
23303
23826
  // empty). Only pass these when explicitly enabling the referee exam stack.
23304
- gatewayCpu = Option37.String("--gateway-cpu");
23305
- gatewayMemory = Option37.String("--gateway-memory");
23306
- refereeEnabled = Option37.String("--referee-enabled");
23307
- refereeBrainRepos = Option37.String("--referee-brain-repos");
23308
- refereeFeedRepo = Option37.String("--referee-feed-repo");
23309
- refereeInstallationId = Option37.String("--referee-installation-id");
23310
- refereeWebhookHmacKvUri = Option37.String("--referee-webhook-hmac-kv-uri");
23311
- examKvUri = Option37.String("--exam-kv-uri");
23312
- examLaWorkspaceId = Option37.String("--exam-la-workspace-id");
23313
- brainEvalDeployment = Option37.String("--brain-eval-deployment");
23314
- brainAppLogin = Option37.String("--brain-app-login");
23315
- refereeCheckpointDir = Option37.String("--referee-checkpoint-dir");
23316
- examApiBase = Option37.String("--exam-api-base");
23827
+ gatewayCpu = Option39.String("--gateway-cpu");
23828
+ gatewayMemory = Option39.String("--gateway-memory");
23829
+ refereeEnabled = Option39.String("--referee-enabled");
23830
+ refereeBrainRepos = Option39.String("--referee-brain-repos");
23831
+ refereeFeedRepo = Option39.String("--referee-feed-repo");
23832
+ refereeInstallationId = Option39.String("--referee-installation-id");
23833
+ refereeWebhookHmacKvUri = Option39.String("--referee-webhook-hmac-kv-uri");
23834
+ examKvUri = Option39.String("--exam-kv-uri");
23835
+ examLaWorkspaceId = Option39.String("--exam-la-workspace-id");
23836
+ brainEvalDeployment = Option39.String("--brain-eval-deployment");
23837
+ brainAppLogin = Option39.String("--brain-app-login");
23838
+ refereeCheckpointDir = Option39.String("--referee-checkpoint-dir");
23839
+ examApiBase = Option39.String("--exam-api-base");
23317
23840
  async executeCommand() {
23318
23841
  const mode = resolveOutputMode(
23319
23842
  this.output,
@@ -23492,7 +24015,7 @@ var DeployCommand = class extends M8tCommand {
23492
24015
 
23493
24016
  // src/commands/eval/skill.ts
23494
24017
  import { spawnSync as spawnSync4 } from "child_process";
23495
- import { Command as Command41, Option as Option38 } from "clipanion";
24018
+ import { Command as Command43, Option as Option40 } from "clipanion";
23496
24019
  init_errors();
23497
24020
  var DECISIONS = /* @__PURE__ */ new Set(["promote", "reject", "needs_review"]);
23498
24021
  var JUDGE_STATUSES = /* @__PURE__ */ new Set(["ok", "skipped", "unavailable"]);
@@ -23517,14 +24040,14 @@ function parseVerdict(stdout) {
23517
24040
  }
23518
24041
  var EvalSkillCommand = class extends M8tCommand {
23519
24042
  static paths = [["eval", "skill"]];
23520
- static usage = Command41.Usage({
24043
+ static usage = Command43.Usage({
23521
24044
  description: "Vet one inbox skill candidate: promote / reject / needs_review. Shells out to the Python `brain-eval` core (override its path with $BRAIN_EVAL_BIN)."
23522
24045
  });
23523
- candidate = Option38.String();
23524
- skillsDir = Option38.String("--skills-dir");
23525
- noJudge = Option38.Boolean("--no-judge", false);
23526
- deployment = Option38.String("--deployment");
23527
- output = Option38.String("--output");
24046
+ candidate = Option40.String();
24047
+ skillsDir = Option40.String("--skills-dir");
24048
+ noJudge = Option40.Boolean("--no-judge", false);
24049
+ deployment = Option40.String("--deployment");
24050
+ output = Option40.String("--output");
23528
24051
  executeCommand() {
23529
24052
  return Promise.resolve(this._runCommand());
23530
24053
  }
@@ -23581,9 +24104,9 @@ var EvalSkillCommand = class extends M8tCommand {
23581
24104
 
23582
24105
  // src/commands/eval/exam.ts
23583
24106
  import { spawnSync as spawnSync5 } from "child_process";
23584
- import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync19, existsSync as existsSync16, readdirSync as readdirSync2 } from "fs";
23585
- import { join as join27 } from "path";
23586
- import { Command as Command42, Option as Option39 } from "clipanion";
24107
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync22, existsSync as existsSync20, readdirSync as readdirSync3 } from "fs";
24108
+ import { join as join31 } from "path";
24109
+ import { Command as Command44, Option as Option41 } from "clipanion";
23587
24110
  init_errors();
23588
24111
  init_esm();
23589
24112
  function parseArmToken(tok, opts) {
@@ -23764,11 +24287,11 @@ function resolveRefereeHome(refereeHomeOut, env) {
23764
24287
  return null;
23765
24288
  }
23766
24289
  function resolveTaskSetDir(base, worker, version) {
23767
- if (existsSync16(join27(base, version))) return version;
24290
+ if (existsSync20(join31(base, version))) return version;
23768
24291
  const prefixed = `${worker}-${version}`;
23769
- if (existsSync16(join27(base, prefixed))) return prefixed;
23770
- if (version === "latest" && existsSync16(base)) {
23771
- const dirs = readdirSync2(base, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.startsWith(`${worker}-`)).map((d) => d.name).sort();
24292
+ if (existsSync20(join31(base, prefixed))) return prefixed;
24293
+ if (version === "latest" && existsSync20(base)) {
24294
+ const dirs = readdirSync3(base, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.startsWith(`${worker}-`)).map((d) => d.name).sort();
23772
24295
  if (dirs.length > 0) return dirs[dirs.length - 1];
23773
24296
  }
23774
24297
  return version;
@@ -23782,11 +24305,11 @@ function readSealedTaskIds(taskSetVersion, refereeHomeOut, env = process.env) {
23782
24305
  message: "cannot resolve the referee home to read the sealed-task manifest \u2014 set $REFEREE_HOME (mirroring the Python runner) so the feed can be redacted; refusing to emit a possibly-unredacted feed (Law-1)"
23783
24306
  });
23784
24307
  }
23785
- const versionDir = resolveTaskSetDir(join27(home, "tasksets", worker), worker, version);
23786
- const manifestPath = join27(home, "tasksets", worker, versionDir, "manifest.yaml");
24308
+ const versionDir = resolveTaskSetDir(join31(home, "tasksets", worker), worker, version);
24309
+ const manifestPath = join31(home, "tasksets", worker, versionDir, "manifest.yaml");
23787
24310
  let text;
23788
24311
  try {
23789
- text = readFileSync19(manifestPath, "utf-8");
24312
+ text = readFileSync22(manifestPath, "utf-8");
23790
24313
  } catch (e) {
23791
24314
  throw new LocalCliError({
23792
24315
  code: "EXAM_REDACTION_UNSAFE",
@@ -23813,24 +24336,24 @@ function buildPlan(args) {
23813
24336
  }
23814
24337
  var EvalExamCommand = class extends M8tCommand {
23815
24338
  static paths = [["eval", "exam"]];
23816
- static usage = Command42.Usage({
24339
+ static usage = Command44.Usage({
23817
24340
  description: "Run a brain exam: impact A/B + dream-delta. Resolves the plan, then shells out to the Python `brain-exam` orchestrator (override its path with $BRAIN_EXAM_BIN). Renders an ExamVerdict: three-valued verdict + power note + per-task flips."
23818
24341
  });
23819
- worker = Option39.String();
23820
- arms = Option39.String("--arms");
23821
- taskSet = Option39.String("--task-set");
23822
- examType = Option39.String("--exam-type");
23823
- skill = Option39.String("--skill");
23824
- reps = Option39.String("-n,--reps");
23825
- probes = Option39.String("--probes");
23826
- pool = Option39.String("--pool");
23827
- out = Option39.String("--out");
23828
- dryRun = Option39.Boolean("--dry-run", false);
23829
- keepArms = Option39.Boolean("--keep-arms", false);
23830
- allowStub = Option39.Boolean("--allow-stub", false);
23831
- deployment = Option39.String("--deployment");
23832
- output = Option39.String("--output");
23833
- observeWaitS = Option39.String("--observe-wait-s");
24342
+ worker = Option41.String();
24343
+ arms = Option41.String("--arms");
24344
+ taskSet = Option41.String("--task-set");
24345
+ examType = Option41.String("--exam-type");
24346
+ skill = Option41.String("--skill");
24347
+ reps = Option41.String("-n,--reps");
24348
+ probes = Option41.String("--probes");
24349
+ pool = Option41.String("--pool");
24350
+ out = Option41.String("--out");
24351
+ dryRun = Option41.Boolean("--dry-run", false);
24352
+ keepArms = Option41.Boolean("--keep-arms", false);
24353
+ allowStub = Option41.Boolean("--allow-stub", false);
24354
+ deployment = Option41.String("--deployment");
24355
+ output = Option41.String("--output");
24356
+ observeWaitS = Option41.String("--observe-wait-s");
23834
24357
  async executeCommand() {
23835
24358
  await Promise.resolve();
23836
24359
  const worker = typeof this.worker === "string" ? this.worker : void 0;
@@ -23906,10 +24429,10 @@ var EvalExamCommand = class extends M8tCommand {
23906
24429
  const verdict = parseExamVerdict(res.stdout);
23907
24430
  if (out !== void 0) {
23908
24431
  const sealedTaskIds = taskSetVersion ? readSealedTaskIds(taskSetVersion, out) : /* @__PURE__ */ new Set();
23909
- mkdirSync5(out, { recursive: true });
23910
- writeFileSync6(join27(out, "verdict.json"), JSON.stringify(verdict, null, 2));
24432
+ mkdirSync6(out, { recursive: true });
24433
+ writeFileSync8(join31(out, "verdict.json"), JSON.stringify(verdict, null, 2));
23911
24434
  const feed = redactForFeed(verdict, sealedTaskIds);
23912
- writeFileSync6(join27(out, "feed.json"), JSON.stringify(feed, null, 2));
24435
+ writeFileSync8(join31(out, "feed.json"), JSON.stringify(feed, null, 2));
23913
24436
  }
23914
24437
  if (mode === "json") {
23915
24438
  this.context.stdout.write(renderJson(verdict) + "\n");
@@ -23945,10 +24468,10 @@ var EvalExamCommand = class extends M8tCommand {
23945
24468
  };
23946
24469
 
23947
24470
  // src/commands/version.ts
23948
- import { Command as Command43, Option as Option40 } from "clipanion";
24471
+ import { Command as Command45, Option as Option42 } from "clipanion";
23949
24472
  var VersionCommand = class extends M8tCommand {
23950
24473
  static paths = [["version"], ["--version"], ["-v"]];
23951
- static usage = Command43.Usage({
24474
+ static usage = Command45.Usage({
23952
24475
  description: "Print the CLI version.",
23953
24476
  details: "Prints the m8t CLI version. With --verbose, also prints Node version and platform.",
23954
24477
  examples: [
@@ -23956,8 +24479,8 @@ var VersionCommand = class extends M8tCommand {
23956
24479
  ["Print as JSON", "$0 version --output json"]
23957
24480
  ]
23958
24481
  });
23959
- output = Option40.String("--output", { description: "pretty | json | auto (default)" });
23960
- verbose = Option40.Boolean("--verbose", false);
24482
+ output = Option42.String("--output", { description: "pretty | json | auto (default)" });
24483
+ verbose = Option42.Boolean("--verbose", false);
23961
24484
  executeCommand() {
23962
24485
  const mode = resolveOutputMode(
23963
24486
  this.output ?? "auto",
@@ -23988,18 +24511,18 @@ var VersionCommand = class extends M8tCommand {
23988
24511
  };
23989
24512
 
23990
24513
  // src/commands/whoami.ts
23991
- import { Command as Command44, Option as Option41 } from "clipanion";
24514
+ import { Command as Command46, Option as Option43 } from "clipanion";
23992
24515
  var WhoamiCommand = class extends M8tCommand {
23993
24516
  static paths = [["whoami"]];
23994
- static usage = Command44.Usage({
24517
+ static usage = Command46.Usage({
23995
24518
  description: "Show your identity + the gateway you'll talk to. Probes the backend."
23996
24519
  });
23997
- output = Option41.String("--output");
23998
- verbose = Option41.Boolean("--verbose", false);
23999
- subscription = Option41.String("--subscription", {
24520
+ output = Option43.String("--output");
24521
+ verbose = Option43.Boolean("--verbose", false);
24522
+ subscription = Option43.String("--subscription", {
24000
24523
  description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
24001
24524
  });
24002
- resourceGroup = Option41.String("--resource-group", {
24525
+ resourceGroup = Option43.String("--resource-group", {
24003
24526
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
24004
24527
  });
24005
24528
  async executeCommand() {
@@ -24064,13 +24587,13 @@ var WhoamiCommand = class extends M8tCommand {
24064
24587
  };
24065
24588
 
24066
24589
  // src/commands/status.ts
24067
- import { Command as Command45, Option as Option42 } from "clipanion";
24590
+ import { Command as Command47, Option as Option44 } from "clipanion";
24068
24591
 
24069
24592
  // src/lib/azd.ts
24070
24593
  init_errors();
24071
24594
  import { spawn as spawn4 } from "child_process";
24072
24595
  function runAzd(args) {
24073
- return new Promise((resolve4, reject) => {
24596
+ return new Promise((resolve6, reject) => {
24074
24597
  const proc = spawn4("azd", args, { stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" });
24075
24598
  const out = [];
24076
24599
  const err = [];
@@ -24099,7 +24622,7 @@ function runAzd(args) {
24099
24622
  );
24100
24623
  return;
24101
24624
  }
24102
- resolve4(Buffer.concat(out).toString("utf8"));
24625
+ resolve6(Buffer.concat(out).toString("utf8"));
24103
24626
  });
24104
24627
  });
24105
24628
  }
@@ -24129,10 +24652,10 @@ async function resolveLocalContext() {
24129
24652
  // src/commands/status.ts
24130
24653
  var StatusCommand = class extends M8tCommand {
24131
24654
  static paths = [["status"]];
24132
- static usage = Command45.Usage({
24655
+ static usage = Command47.Usage({
24133
24656
  description: "Show the local m8t context: identity, config.yaml, gateway cache, azd mode."
24134
24657
  });
24135
- output = Option42.String("--output");
24658
+ output = Option44.String("--output");
24136
24659
  async executeCommand() {
24137
24660
  const mode = resolveOutputMode(
24138
24661
  this.output,
@@ -24170,11 +24693,11 @@ var StatusCommand = class extends M8tCommand {
24170
24693
  };
24171
24694
 
24172
24695
  // src/commands/doctor.ts
24173
- import { Command as Command46, Option as Option43 } from "clipanion";
24696
+ import { Command as Command48, Option as Option45 } from "clipanion";
24174
24697
  import { DefaultAzureCredential as DefaultAzureCredential22 } from "@azure/identity";
24175
- import * as fs26 from "fs";
24176
- import * as os11 from "os";
24177
- import * as path29 from "path";
24698
+ import * as fs31 from "fs";
24699
+ import * as os12 from "os";
24700
+ import * as path34 from "path";
24178
24701
 
24179
24702
  // src/lib/doctor-checks.ts
24180
24703
  function checkAzSignedIn(az) {
@@ -24653,40 +25176,40 @@ async function resolveAccountLocation(accountId) {
24653
25176
  }
24654
25177
  }
24655
25178
  function probeRepoRoot() {
24656
- const marker = path29.join(os11.homedir(), ".m8t", "repo-root");
24657
- if (!fs26.existsSync(marker)) {
25179
+ const marker = path34.join(os12.homedir(), ".m8t", "repo-root");
25180
+ if (!fs31.existsSync(marker)) {
24658
25181
  return { markerExists: false, path: null, isDir: false, isGitCheckout: false };
24659
25182
  }
24660
25183
  let repoPath;
24661
25184
  try {
24662
- repoPath = fs26.readFileSync(marker, "utf8").trim();
25185
+ repoPath = fs31.readFileSync(marker, "utf8").trim();
24663
25186
  } catch {
24664
25187
  return { markerExists: true, path: null, isDir: false, isGitCheckout: false };
24665
25188
  }
24666
25189
  if (!repoPath) return { markerExists: true, path: null, isDir: false, isGitCheckout: false };
24667
25190
  let isDir = false;
24668
25191
  try {
24669
- isDir = fs26.statSync(repoPath).isDirectory();
25192
+ isDir = fs31.statSync(repoPath).isDirectory();
24670
25193
  } catch {
24671
25194
  isDir = false;
24672
25195
  }
24673
- const isGitCheckout = isDir && fs26.existsSync(path29.join(repoPath, ".git"));
25196
+ const isGitCheckout = isDir && fs31.existsSync(path34.join(repoPath, ".git"));
24674
25197
  return { markerExists: true, path: repoPath, isDir, isGitCheckout };
24675
25198
  }
24676
25199
  function probeLegacyStateDir() {
24677
25200
  return {
24678
- legacyExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t-stack")),
24679
- currentExists: fs26.existsSync(path29.join(os11.homedir(), ".m8t"))
25201
+ legacyExists: fs31.existsSync(path34.join(os12.homedir(), ".m8t-stack")),
25202
+ currentExists: fs31.existsSync(path34.join(os12.homedir(), ".m8t"))
24680
25203
  };
24681
25204
  }
24682
25205
  var DoctorCommand = class extends M8tCommand {
24683
25206
  static paths = [["doctor"]];
24684
- static usage = Command46.Usage({
25207
+ static usage = Command48.Usage({
24685
25208
  description: "Diagnose the local m8t setup: az login, config.yaml, gateway, Foundry data-plane."
24686
25209
  });
24687
- output = Option43.String("--output");
24688
- agent = Option43.String("--agent");
24689
- resourceGroup = Option43.String("--resource-group", {
25210
+ output = Option45.String("--output");
25211
+ agent = Option45.String("--agent");
25212
+ resourceGroup = Option45.String("--resource-group", {
24690
25213
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
24691
25214
  });
24692
25215
  async executeCommand() {
@@ -24822,7 +25345,7 @@ var DoctorCommand = class extends M8tCommand {
24822
25345
  };
24823
25346
 
24824
25347
  // src/commands/prereqs.ts
24825
- import { Command as Command47, Option as Option44 } from "clipanion";
25348
+ import { Command as Command49, Option as Option46 } from "clipanion";
24826
25349
  init_errors();
24827
25350
 
24828
25351
  // src/lib/prereq-deps.ts
@@ -25528,7 +26051,7 @@ function renderVerdict(v) {
25528
26051
  }
25529
26052
  var PrereqsCommand = class extends M8tCommand {
25530
26053
  static paths = [["prereqs"]];
25531
- static usage = Command47.Usage({
26054
+ static usage = Command49.Usage({
25532
26055
  description: "Check (and optionally fix) everything m8t needs \u2014 to install, or for you to use it.",
25533
26056
  details: "Runs one of two phases. With no platform discoverable it checks INSTALL prerequisites: your Azure sign-in, subscription and directory rights, resource-provider registrations, soft-deleted Cognitive Services accounts (they hold their model quota until purged), and model quota. With a platform live it checks USAGE prerequisites for the signed-in account: the sign-in redirect URI, Foundry data-plane access, and Key Vault secrets access. Pass --fix to repair what is repairable, and --fix --for <upn> to set a teammate up (usage phase only). Read-only without --fix.",
25534
26057
  examples: [
@@ -25539,15 +26062,15 @@ var PrereqsCommand = class extends M8tCommand {
25539
26062
  ["Set a teammate up (needs role-assignment rights)", "$0 prereqs --fix --for alice@contoso.com"]
25540
26063
  ]
25541
26064
  });
25542
- fix = Option44.Boolean("--fix", false, { description: "Repair what is repairable. Without it the command only reports." });
25543
- for_ = Option44.String("--for", { description: "UPN or object id of another person. Usage phase only." });
25544
- phase = Option44.String("--phase", { description: "Force 'install' or 'usage' instead of auto-detecting." });
25545
- region = Option44.String("--region", { description: "Target region. Enables the install-phase quota check, and judges soft-deleted accounts against the region you will install into (without it, they only warn)." });
25546
- model = Option44.String("--model", { description: `Model whose quota the install needs (default ${INSTALL_REASONING_MODEL}).` });
25547
- clientId = Option44.String("--client-id", { description: "A ready app registration, in place of directory-admin rights." });
25548
- subscription = Option44.String("--subscription");
25549
- resourceGroup = Option44.String("--resource-group");
25550
- output = Option44.String("--output");
26065
+ fix = Option46.Boolean("--fix", false, { description: "Repair what is repairable. Without it the command only reports." });
26066
+ for_ = Option46.String("--for", { description: "UPN or object id of another person. Usage phase only." });
26067
+ phase = Option46.String("--phase", { description: "Force 'install' or 'usage' instead of auto-detecting." });
26068
+ region = Option46.String("--region", { description: "Target region. Enables the install-phase quota check, and judges soft-deleted accounts against the region you will install into (without it, they only warn)." });
26069
+ model = Option46.String("--model", { description: `Model whose quota the install needs (default ${INSTALL_REASONING_MODEL}).` });
26070
+ clientId = Option46.String("--client-id", { description: "A ready app registration, in place of directory-admin rights." });
26071
+ subscription = Option46.String("--subscription");
26072
+ resourceGroup = Option46.String("--resource-group");
26073
+ output = Option46.String("--output");
25551
26074
  async executeCommand() {
25552
26075
  const mode = resolveOutputMode(this.output, this.context.stdout);
25553
26076
  const json = mode === "json";
@@ -25603,18 +26126,18 @@ var PrereqsCommand = class extends M8tCommand {
25603
26126
  };
25604
26127
 
25605
26128
  // src/commands/switch.ts
25606
- import { Command as Command48, Option as Option45 } from "clipanion";
26129
+ import { Command as Command50, Option as Option47 } from "clipanion";
25607
26130
 
25608
26131
  // src/lib/profiles.ts
25609
- import * as fs27 from "fs/promises";
25610
- import * as path30 from "path";
25611
- import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
26132
+ import * as fs32 from "fs/promises";
26133
+ import * as path35 from "path";
26134
+ import { parse as parseYaml12, stringify as stringifyYaml4 } from "yaml";
25612
26135
  function profilesDir() {
25613
26136
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
25614
- return path30.join(home, ".m8t", "profiles");
26137
+ return path35.join(home, ".m8t", "profiles");
25615
26138
  }
25616
26139
  function getProfilePath(name) {
25617
- return path30.join(profilesDir(), `${path30.basename(name)}.yaml`);
26140
+ return path35.join(profilesDir(), `${path35.basename(name)}.yaml`);
25618
26141
  }
25619
26142
  function slugifyTenant(domainOrId) {
25620
26143
  const base = domainOrId.split(".")[0].toLowerCase();
@@ -25623,7 +26146,7 @@ function slugifyTenant(domainOrId) {
25623
26146
  }
25624
26147
  async function listProfiles() {
25625
26148
  try {
25626
- const entries = await fs27.readdir(profilesDir());
26149
+ const entries = await fs32.readdir(profilesDir());
25627
26150
  return entries.filter((e) => e.endsWith(".yaml")).map((e) => e.replace(/\.yaml$/, "")).sort();
25628
26151
  } catch (e) {
25629
26152
  if (e.code === "ENOENT") return [];
@@ -25632,8 +26155,8 @@ async function listProfiles() {
25632
26155
  }
25633
26156
  async function readProfile(name) {
25634
26157
  try {
25635
- const raw = await fs27.readFile(getProfilePath(name), "utf8");
25636
- const parsed = parseYaml11(raw);
26158
+ const raw = await fs32.readFile(getProfilePath(name), "utf8");
26159
+ const parsed = parseYaml12(raw);
25637
26160
  if (!parsed || typeof parsed !== "object") return null;
25638
26161
  return parsed;
25639
26162
  } catch (e) {
@@ -25643,14 +26166,14 @@ async function readProfile(name) {
25643
26166
  }
25644
26167
  async function exists(p) {
25645
26168
  try {
25646
- await fs27.stat(p);
26169
+ await fs32.stat(p);
25647
26170
  return true;
25648
26171
  } catch {
25649
26172
  return false;
25650
26173
  }
25651
26174
  }
25652
26175
  async function saveProfile(p) {
25653
- await fs27.mkdir(profilesDir(), { recursive: true });
26176
+ await fs32.mkdir(profilesDir(), { recursive: true });
25654
26177
  let name = p.name;
25655
26178
  let n = 2;
25656
26179
  while (await exists(getProfilePath(name))) {
@@ -25659,8 +26182,8 @@ async function saveProfile(p) {
25659
26182
  }
25660
26183
  const target = getProfilePath(name);
25661
26184
  const tmp = `${target}.tmp`;
25662
- await fs27.writeFile(tmp, stringifyYaml4({ ...p, name }, { indent: 2 }), "utf8");
25663
- await fs27.rename(tmp, target);
26185
+ await fs32.writeFile(tmp, stringifyYaml4({ ...p, name }, { indent: 2 }), "utf8");
26186
+ await fs32.rename(tmp, target);
25664
26187
  return name;
25665
26188
  }
25666
26189
 
@@ -25743,14 +26266,14 @@ async function profileSwitch(name, asName) {
25743
26266
  init_errors();
25744
26267
  var SwitchCommand = class extends M8tCommand {
25745
26268
  static paths = [["switch"]];
25746
- static usage = Command48.Usage({
26269
+ static usage = Command50.Usage({
25747
26270
  description: "Re-point local config at another deployment: --subscription <id|name> (discovery) or <profile>."
25748
26271
  });
25749
- profile = Option45.String({ required: false });
25750
- subscription = Option45.String("--subscription");
25751
- list = Option45.Boolean("--list", false);
25752
- as = Option45.String("--as");
25753
- output = Option45.String("--output");
26272
+ profile = Option47.String({ required: false });
26273
+ subscription = Option47.String("--subscription");
26274
+ list = Option47.Boolean("--list", false);
26275
+ as = Option47.String("--as");
26276
+ output = Option47.String("--output");
25754
26277
  async executeCommand() {
25755
26278
  const mode = resolveOutputMode(
25756
26279
  this.output,
@@ -25807,7 +26330,7 @@ var SwitchCommand = class extends M8tCommand {
25807
26330
 
25808
26331
  // src/commands/open.ts
25809
26332
  import { spawn as spawn5 } from "child_process";
25810
- import { Command as Command49, Option as Option46 } from "clipanion";
26333
+ import { Command as Command51, Option as Option48 } from "clipanion";
25811
26334
 
25812
26335
  // src/lib/open-targets.ts
25813
26336
  init_errors();
@@ -25853,14 +26376,14 @@ function openUrl(url) {
25853
26376
  }
25854
26377
  var OpenCommand = class extends M8tCommand {
25855
26378
  static paths = [["open"]];
25856
- static usage = Command49.Usage({
26379
+ static usage = Command51.Usage({
25857
26380
  description: "Open the deployed webapp (default), the Foundry portal, or the resource group.",
25858
26381
  details: "Targets: webapp (deployed app, default) | foundry (ai.azure.com) | portal (resource group in the Azure portal). Pass --print to emit the URL instead of launching a browser (also the default when stdout isn't a TTY)."
25859
26382
  });
25860
- target = Option46.String({ required: false });
25861
- print = Option46.Boolean("--print", false);
25862
- output = Option46.String("--output");
25863
- resourceGroup = Option46.String("--resource-group", {
26383
+ target = Option48.String({ required: false });
26384
+ print = Option48.Boolean("--print", false);
26385
+ output = Option48.String("--output");
26386
+ resourceGroup = Option48.String("--resource-group", {
25864
26387
  description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
25865
26388
  });
25866
26389
  async executeCommand() {
@@ -25904,7 +26427,7 @@ var OpenCommand = class extends M8tCommand {
25904
26427
  };
25905
26428
 
25906
26429
  // src/commands/dream/run.ts
25907
- import { Command as Command50, Option as Option47 } from "clipanion";
26430
+ import { Command as Command52, Option as Option49 } from "clipanion";
25908
26431
  import { AzureCliCredential } from "@azure/identity";
25909
26432
  import { TableClient as TableClient7 } from "@azure/data-tables";
25910
26433
  import { AIProjectClient as AIProjectClient3 } from "@azure/ai-projects";
@@ -26890,7 +27413,7 @@ function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedT
26890
27413
  // ../../packages/brain/engine/dist/esm/dream/writer.js
26891
27414
  var API2 = "https://api.github.com";
26892
27415
  var WRITER_ALLOWED_PREFIX = /^(memory|inbox|quarantine|artifacts)\//;
26893
- var isAllowedWritePath = (path43, allowedPrefix) => allowedPrefix.test(path43) && !path43.split("/").includes("..");
27416
+ var isAllowedWritePath = (path48, allowedPrefix) => allowedPrefix.test(path48) && !path48.split("/").includes("..");
26894
27417
  var unquote = (s) => s.trim().replace(/^["']|["']$/g, "");
26895
27418
  function parseFrontmatter(content) {
26896
27419
  const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
@@ -26933,8 +27456,8 @@ function makeGitDataWriter(args) {
26933
27456
  if (args.allowedPathPrefix && !args.allowedPathPrefix.source.startsWith("^")) {
26934
27457
  throw new Error(`makeGitDataWriter: allowedPathPrefix must be anchored with "^" (got /${args.allowedPathPrefix.source}/) \u2014 an unanchored regex would widen the B1 write-path allowlist`);
26935
27458
  }
26936
- async function gh(token, method, path43, body) {
26937
- const res = await doFetch(`${API2}/repos/${repoPath}${path43}`, {
27459
+ async function gh(token, method, path48, body) {
27460
+ const res = await doFetch(`${API2}/repos/${repoPath}${path48}`, {
26938
27461
  method,
26939
27462
  headers: {
26940
27463
  Authorization: `Bearer ${token}`,
@@ -26947,8 +27470,8 @@ function makeGitDataWriter(args) {
26947
27470
  const text = await res.text();
26948
27471
  return { status: res.status, ok: res.ok, json: text ? JSON.parse(text) : {} };
26949
27472
  }
26950
- async function readFileWith(token, path43) {
26951
- const encodedPath = path43.split("/").map(encodeURIComponent).join("/");
27473
+ async function readFileWith(token, path48) {
27474
+ const encodedPath = path48.split("/").map(encodeURIComponent).join("/");
26952
27475
  const r = await gh(token, "GET", `/contents/${encodedPath}?ref=${args.branch}`);
26953
27476
  if (r.status === 404)
26954
27477
  return null;
@@ -26964,9 +27487,9 @@ function makeGitDataWriter(args) {
26964
27487
  throw new Error(`fetchTip: HTTP ${String(r.status)}`);
26965
27488
  return r.json.object.sha;
26966
27489
  },
26967
- async readFile(path43) {
27490
+ async readFile(path48) {
26968
27491
  const token = await args.mintToken();
26969
- return readFileWith(token, path43);
27492
+ return readFileWith(token, path48);
26970
27493
  },
26971
27494
  async listMemory() {
26972
27495
  const token = await args.mintToken();
@@ -26975,9 +27498,9 @@ function makeGitDataWriter(args) {
26975
27498
  return [];
26976
27499
  const paths = r.json.tree.filter((e) => e.type === "blob" && e.path.startsWith("memory/") && e.path.endsWith(".md")).map((e) => e.path);
26977
27500
  const out = [];
26978
- for (const path43 of paths) {
26979
- const content = await readFileWith(token, path43);
26980
- out.push({ path: path43, frontmatter: content ? parseFrontmatter(content) : {} });
27501
+ for (const path48 of paths) {
27502
+ const content = await readFileWith(token, path48);
27503
+ out.push({ path: path48, frontmatter: content ? parseFrontmatter(content) : {} });
26981
27504
  }
26982
27505
  return out;
26983
27506
  },
@@ -27416,7 +27939,7 @@ async function loadMemoryContext(brain) {
27416
27939
  return {
27417
27940
  files,
27418
27941
  indexEntries,
27419
- originOf: (path43) => originByPath.get(path43) ?? "worker"
27942
+ originOf: (path48) => originByPath.get(path48) ?? "worker"
27420
27943
  };
27421
27944
  }
27422
27945
 
@@ -27437,14 +27960,14 @@ function checkEvidenceMembership(delta, harvested) {
27437
27960
  }
27438
27961
  var BatchAbort = class extends Error {
27439
27962
  path;
27440
- constructor(path43, message) {
27963
+ constructor(path48, message) {
27441
27964
  super(message);
27442
- this.path = path43;
27965
+ this.path = path48;
27443
27966
  this.name = "BatchAbort";
27444
27967
  }
27445
27968
  };
27446
- var isIndexFile = (path43) => /(^|\/)[^/]*_index\.md$/.test(path43);
27447
- var isMemoryIndex = (path43) => path43 === "memory/MEMORY.md";
27969
+ var isIndexFile = (path48) => /(^|\/)[^/]*_index\.md$/.test(path48);
27970
+ var isMemoryIndex = (path48) => path48 === "memory/MEMORY.md";
27448
27971
  function targetPath(delta) {
27449
27972
  switch (delta.verb) {
27450
27973
  case "new":
@@ -27461,29 +27984,29 @@ function targetPath(delta) {
27461
27984
  }
27462
27985
  async function checkOriginTier(delta, lookup) {
27463
27986
  const evidence = evidenceOf(delta) ?? [];
27464
- const path43 = targetPath(delta);
27465
- if (path43 === null)
27987
+ const path48 = targetPath(delta);
27988
+ if (path48 === null)
27466
27989
  return { ok: true };
27467
- if (isIndexFile(path43) && !isMemoryIndex(path43)) {
27468
- return { ok: false, flagged: { kind: "flagged", path: path43, tension: `refused: ${path43} is an index file (only memory/MEMORY.md is editable)`, evidence } };
27990
+ if (isIndexFile(path48) && !isMemoryIndex(path48)) {
27991
+ return { ok: false, flagged: { kind: "flagged", path: path48, tension: `refused: ${path48} is an index file (only memory/MEMORY.md is editable)`, evidence } };
27469
27992
  }
27470
- const target = await lookup(path43);
27471
- const isStructural = path43.startsWith("references/");
27993
+ const target = await lookup(path48);
27994
+ const isStructural = path48.startsWith("references/");
27472
27995
  const origin = target?.frontmatter.origin ?? (isStructural ? "operator" : "worker");
27473
27996
  const editable = origin === "worker" || origin === "dream";
27474
27997
  if (editable)
27475
27998
  return { ok: true };
27476
27999
  const removesOperatorTarget = delta.verb === "retract" || delta.verb === "supersede" && delta.oldPath !== delta.newPath;
27477
28000
  if (removesOperatorTarget) {
27478
- throw new BatchAbort(path43, `supersede/retract OLD target ${path43} is origin: ${origin} \u2014 aborting batch (never half-apply)`);
28001
+ throw new BatchAbort(path48, `supersede/retract OLD target ${path48} is origin: ${origin} \u2014 aborting batch (never half-apply)`);
27479
28002
  }
27480
- return { ok: false, flagged: { kind: "flagged", path: path43, tension: `operator-origin (${origin}); flag-only`, evidence } };
28003
+ return { ok: false, flagged: { kind: "flagged", path: path48, tension: `operator-origin (${origin}); flag-only`, evidence } };
27481
28004
  }
27482
28005
  var ALLOWED_MEMORY = /^memory\/.+\.md$/;
27483
28006
  var ALLOWED_INBOX = /^inbox\//;
27484
28007
  var ALLOWED_QUARANTINE = /^quarantine\//;
27485
28008
  var ALLOWED_FLAG = /^memory\//;
27486
- var hasTraversal = (path43) => path43.split("/").includes("..");
28009
+ var hasTraversal = (path48) => path48.split("/").includes("..");
27487
28010
  function checkPathAllowed(delta) {
27488
28011
  const evidence = evidenceOf(delta) ?? [];
27489
28012
  const reject = (detail) => ({ ok: false, rejected: { kind: "rejected", detail, evidence } });
@@ -27590,7 +28113,7 @@ ${inject}
27590
28113
  ---
27591
28114
  ` + body.slice(m[0].length);
27592
28115
  }
27593
- var indexLine = (path43, title, date, tags) => `- \`${path43}\` \u2014 **${title}**: ${title}. (${date} \xB7 ${tags.join(", ")})`;
28116
+ var indexLine = (path48, title, date, tags) => `- \`${path48}\` \u2014 **${title}**: ${title}. (${date} \xB7 ${tags.join(", ")})`;
27594
28117
  function splitIndex(index) {
27595
28118
  const all = index.split("\n");
27596
28119
  const firstLineIdx = all.findIndex((l) => l.startsWith("- `memory/"));
@@ -27763,16 +28286,16 @@ function defaultDreamSeams(opts = {}) {
27763
28286
  const mem = await memory(deps.brain);
27764
28287
  const harvested = harvestedIds(input);
27765
28288
  const ctx = { readFile: (p) => deps.brain.readFile(p), at: deps.clock() };
27766
- const lookup = (path43) => Promise.resolve(mem.files.find((f) => f.path === path43) ?? null);
28289
+ const lookup = (path48) => Promise.resolve(mem.files.find((f) => f.path === path48) ?? null);
27767
28290
  const digest = [...pendingRejected];
27768
28291
  let changes = [];
27769
28292
  let indexEdit;
27770
28293
  try {
27771
28294
  for (const raw of deltas) {
27772
28295
  const delta = forcePolicyQuarantine(raw);
27773
- const path43 = checkPathAllowed(delta);
27774
- if (!path43.ok) {
27775
- digest.push(path43.rejected);
28296
+ const path48 = checkPathAllowed(delta);
28297
+ if (!path48.ok) {
28298
+ digest.push(path48.rejected);
27776
28299
  continue;
27777
28300
  }
27778
28301
  const ev = checkEvidenceMembership(delta, harvested);
@@ -27986,7 +28509,7 @@ async function emitDigest(input, deps, digest) {
27986
28509
  }
27987
28510
 
27988
28511
  // ../../packages/brain/engine/dist/esm/dream/config.js
27989
- import { parse as parseYaml12 } from "yaml";
28512
+ import { parse as parseYaml13 } from "yaml";
27990
28513
  var DEFAULT_DREAM_MODEL = "gpt-5.4";
27991
28514
  function asCadence(v) {
27992
28515
  return v === "nightly" ? "nightly" : "off";
@@ -27994,7 +28517,7 @@ function asCadence(v) {
27994
28517
  function parseDreamerConfig(rawYaml, env) {
27995
28518
  let parsed;
27996
28519
  try {
27997
- parsed = parseYaml12(rawYaml);
28520
+ parsed = parseYaml13(rawYaml);
27998
28521
  } catch {
27999
28522
  return { enabled: false, cadence: "off", model: env.M8T_DREAM_MODEL ?? DEFAULT_DREAM_MODEL };
28000
28523
  }
@@ -28008,16 +28531,16 @@ function parseDreamerConfig(rawYaml, env) {
28008
28531
  }
28009
28532
 
28010
28533
  // ../../packages/brain/engine/dist/esm/cost-report/config.js
28011
- import { parse as parseYaml13 } from "yaml";
28534
+ import { parse as parseYaml14 } from "yaml";
28012
28535
 
28013
28536
  // ../../packages/brain/engine/dist/esm/librarian/codify/persistence-guard.js
28014
28537
  var ZERO_WIDTH_RE = new RegExp("\u200B|\u200C|\u200D|\uFEFF", "g");
28015
28538
 
28016
28539
  // ../../packages/brain/engine/dist/esm/librarian/janitor/frontmatter.js
28017
- import { parse as parseYaml14, stringify as stringifyYaml5 } from "yaml";
28540
+ import { parse as parseYaml15, stringify as stringifyYaml5 } from "yaml";
28018
28541
 
28019
28542
  // ../../packages/brain/engine/dist/esm/librarian/config.js
28020
- import { parse as parseYaml15 } from "yaml";
28543
+ import { parse as parseYaml16 } from "yaml";
28021
28544
 
28022
28545
  // src/lib/dream-discovery.ts
28023
28546
  init_http();
@@ -28131,25 +28654,25 @@ function redactTranscripts(input) {
28131
28654
  }
28132
28655
  var DreamRunCommand = class extends M8tCommand {
28133
28656
  static paths = [["dream", "run"]];
28134
- static usage = Command50.Usage({
28657
+ static usage = Command52.Usage({
28135
28658
  description: "Dry-run the brain consumption pipeline for one worker (no model call, no writes). Pass --live to actually run it.",
28136
28659
  details: "Builds AzureCliCredential + resolves the Foundry project, ledger table, and Log Analytics workspace, runs the consumption pipeline, and prints the skip-ledger, the partition invariant, and harvest stats. Transcripts are metadata-only unless --show-transcripts is passed.\n\nThe bare command is READ-ONLY. --live takes the other branch: a real model call and a commit to the worker's brain repo through a minted GitHub App token."
28137
28660
  });
28138
- worker = Option47.String("--worker", { description: "Worker (canonical name) to harvest. Required." });
28661
+ worker = Option49.String("--worker", { description: "Worker (canonical name) to harvest. Required." });
28139
28662
  // Opting IN to the side effects, rather than opting out of them. This command's
28140
28663
  // own help has always described a dry run, but the bare invocation used to take
28141
28664
  // the live branch — a real model call and a commit to the brain repo — so anyone
28142
28665
  // acting on `--help` got the opposite of what they read.
28143
- live = Option47.Boolean("--live", false, { description: "Actually run it: model call + commit to the brain repo." });
28144
- dryRun = Option47.Boolean("--dry-run", false, { description: "Read-only harvest. This is the default; the flag is accepted for compatibility." });
28145
- since = Option47.String("--since", { description: "ISO-8601 start override (rejected if malformed or future)." });
28146
- reset = Option47.Boolean("--reset", false, { description: "Ignore the stored cursor; read from the beginning." });
28147
- showTranscripts = Option47.Boolean("--show-transcripts", false, {
28666
+ live = Option49.Boolean("--live", false, { description: "Actually run it: model call + commit to the brain repo." });
28667
+ dryRun = Option49.Boolean("--dry-run", false, { description: "Read-only harvest. This is the default; the flag is accepted for compatibility." });
28668
+ since = Option49.String("--since", { description: "ISO-8601 start override (rejected if malformed or future)." });
28669
+ reset = Option49.Boolean("--reset", false, { description: "Ignore the stored cursor; read from the beginning." });
28670
+ showTranscripts = Option49.Boolean("--show-transcripts", false, {
28148
28671
  description: "Print transcript bodies (default: metadata only)."
28149
28672
  });
28150
- subscription = Option47.String("--subscription");
28151
- endpoint = Option47.String("--endpoint");
28152
- output = Option47.String("--output");
28673
+ subscription = Option49.String("--subscription");
28674
+ endpoint = Option49.String("--endpoint");
28675
+ output = Option49.String("--output");
28153
28676
  // Resolution seam — overridden by tests; built lazily at runtime otherwise.
28154
28677
  deps;
28155
28678
  async executeCommand() {
@@ -28497,13 +29020,13 @@ function defaultDeps(overrides) {
28497
29020
  }
28498
29021
 
28499
29022
  // src/commands/foundry/create.ts
28500
- import { Command as Command51, Option as Option48 } from "clipanion";
29023
+ import { Command as Command53, Option as Option50 } from "clipanion";
28501
29024
 
28502
29025
  // src/lib/foundry-create.ts
28503
29026
  init_errors();
28504
- import { createHash as createHash3 } from "crypto";
29027
+ import { createHash as createHash4 } from "crypto";
28505
29028
  function deriveAccountName(subscriptionId) {
28506
- const h = createHash3("sha256").update(subscriptionId).digest("hex").slice(0, 12);
29029
+ const h = createHash4("sha256").update(subscriptionId).digest("hex").slice(0, 12);
28507
29030
  return `m8t${h}`;
28508
29031
  }
28509
29032
  function assertHostedRegion(location) {
@@ -28566,8 +29089,8 @@ async function ensureAccount(args) {
28566
29089
  );
28567
29090
  } catch (e) {
28568
29091
  const msg = e instanceof Error ? e.message : String(e);
28569
- const sep3 = "' failed: ";
28570
- const stderr = msg.includes(sep3) ? msg.slice(msg.indexOf(sep3) + sep3.length) : msg;
29092
+ const sep4 = "' failed: ";
29093
+ const stderr = msg.includes(sep4) ? msg.slice(msg.indexOf(sep4) + sep4.length) : msg;
28571
29094
  if (/CustomDomainInUse|subdomain name .* is not available|already used by a resource/i.test(stderr)) {
28572
29095
  throw new LocalCliError({
28573
29096
  code: "FOUNDRY_ACCOUNT_SUBDOMAIN_CONFLICT",
@@ -28735,7 +29258,7 @@ async function createFoundryProject(args) {
28735
29258
  init_errors();
28736
29259
  var FoundryCreateCommand = class extends M8tCommand {
28737
29260
  static paths = [["foundry", "create"]];
28738
- static usage = Command51.Usage({
29261
+ static usage = Command53.Usage({
28739
29262
  description: "Create an AI Foundry (AIServices) account + project + model deployment from scratch.",
28740
29263
  details: "Non-interactive and idempotent. Creates the AIServices account (custom subdomain + project management), a project, and a model deployment (default gpt-4.1-mini @ capacity 50). Region must be hosted-agent-eligible. Emits the project endpoint as structured output. Re-run is a clean no-op (account/project skipped if present; deployment capacity converges UP, never down).",
28741
29264
  examples: [
@@ -28744,16 +29267,16 @@ var FoundryCreateCommand = class extends M8tCommand {
28744
29267
  ["Higher capacity for a reasoning model", "$0 foundry create --resource-group rg-m8t-stack --location eastus2 --model gpt-5-mini --capacity 250"]
28745
29268
  ]
28746
29269
  });
28747
- resourceGroup = Option48.String("--resource-group");
28748
- location = Option48.String("--location");
28749
- account = Option48.String("--account");
28750
- project = Option48.String("--project", "m8t");
28751
- model = Option48.String("--model", "gpt-4.1-mini");
28752
- modelVersion = Option48.String("--model-version", "2025-04-14");
28753
- capacity = Option48.String("--capacity", "50");
28754
- subscription = Option48.String("--subscription");
28755
- skipQuotaCheck = Option48.Boolean("--skip-quota-check", false);
28756
- output = Option48.String("--output");
29270
+ resourceGroup = Option50.String("--resource-group");
29271
+ location = Option50.String("--location");
29272
+ account = Option50.String("--account");
29273
+ project = Option50.String("--project", "m8t");
29274
+ model = Option50.String("--model", "gpt-4.1-mini");
29275
+ modelVersion = Option50.String("--model-version", "2025-04-14");
29276
+ capacity = Option50.String("--capacity", "50");
29277
+ subscription = Option50.String("--subscription");
29278
+ skipQuotaCheck = Option50.Boolean("--skip-quota-check", false);
29279
+ output = Option50.String("--output");
28757
29280
  async executeCommand() {
28758
29281
  const mode = resolveOutputMode(
28759
29282
  this.output,
@@ -28825,22 +29348,22 @@ var FoundryCreateCommand = class extends M8tCommand {
28825
29348
  };
28826
29349
 
28827
29350
  // src/commands/foundry/await-ready.ts
28828
- import { Command as Command52, Option as Option49 } from "clipanion";
29351
+ import { Command as Command54, Option as Option51 } from "clipanion";
28829
29352
  import { AzureCliCredential as AzureCliCredential2 } from "@azure/identity";
28830
29353
  init_errors();
28831
29354
  var FoundryAwaitReadyCommand = class extends M8tCommand {
28832
29355
  static paths = [["foundry", "await-ready"]];
28833
- static usage = Command52.Usage({
29356
+ static usage = Command54.Usage({
28834
29357
  description: "Wait until a freshly-created Foundry project's data plane reliably serves it.",
28835
29358
  details: "Probes the project (GET /agents) until it returns 200 on a few consecutive tries, or fails clearly after a bounded budget. A newly-created account can serve intermittent 404 'Project not found' for minutes; run this after 'foundry create' and before deploying agents so the worker phase doesn't catch the unstable window.",
28836
29359
  examples: [["Wait for a project to be ready", "$0 foundry await-ready --endpoint https://acc.services.ai.azure.com/api/projects/m8t"]]
28837
29360
  });
28838
- endpoint = Option49.String("--endpoint");
28839
- consecutive = Option49.String("--consecutive", "3");
28840
- attempts = Option49.String("--attempts", "60");
28841
- interval = Option49.String("--interval", "5");
28842
- subscription = Option49.String("--subscription");
28843
- output = Option49.String("--output");
29361
+ endpoint = Option51.String("--endpoint");
29362
+ consecutive = Option51.String("--consecutive", "3");
29363
+ attempts = Option51.String("--attempts", "60");
29364
+ interval = Option51.String("--interval", "5");
29365
+ subscription = Option51.String("--subscription");
29366
+ output = Option51.String("--output");
28844
29367
  async executeCommand() {
28845
29368
  const mode = resolveOutputMode(this.output, this.context.stdout);
28846
29369
  const endpoint = typeof this.endpoint === "string" ? this.endpoint : void 0;
@@ -28874,7 +29397,7 @@ var FoundryAwaitReadyCommand = class extends M8tCommand {
28874
29397
  };
28875
29398
 
28876
29399
  // src/commands/bootstrap/preflight.ts
28877
- import { Command as Command53, Option as Option50 } from "clipanion";
29400
+ import { Command as Command55, Option as Option52 } from "clipanion";
28878
29401
 
28879
29402
  // ../../packages/telemetry-contract/artifact/tier-map.ts
28880
29403
  var EVENT_TIERS = {
@@ -28900,9 +29423,9 @@ var DISCLOSURE_TIER1 = "Operational data. To support your installation, m8t rece
28900
29423
 
28901
29424
  // ../../packages/telemetry-contract/src/endpoints.ts
28902
29425
  var INGEST_BASE_URL = (process.env.M8T_INGEST_BASE_URL ?? "").trim() || "https://m8t-admin.wonderfuldesert-721e332f.eastus2.azurecontainerapps.io";
28903
- function ingestUrl(path43) {
29426
+ function ingestUrl(path48) {
28904
29427
  const base = INGEST_BASE_URL.replace(/\/+$/, "");
28905
- return `${base}${path43.startsWith("/") ? path43 : `/${path43}`}`;
29428
+ return `${base}${path48.startsWith("/") ? path48 : `/${path48}`}`;
28906
29429
  }
28907
29430
 
28908
29431
  // src/commands/bootstrap/preflight.ts
@@ -28926,7 +29449,7 @@ function preflightRenderable(results) {
28926
29449
  }
28927
29450
  var BootstrapPreflightCommand = class extends M8tCommand {
28928
29451
  static paths = [["bootstrap", "preflight"]];
28929
- static usage = Command53.Usage({
29452
+ static usage = Command55.Usage({
28930
29453
  description: "Loudly verify you can install m8t (Owner/UAA + directory admin) and hard-stop if not.",
28931
29454
  details: "Step 1 of `m8t bootstrap`. Prints an unmissable admin-credentials notice, then checks: Owner or User Access Administrator at subscription scope (hard requirement), directory-admin capability to register the app (or pass --client-id), every Azure resource provider the install uses (registering any that are missing), soft-deleted Cognitive Services accounts (they keep their model quota until purged, so quota can read free and the model deployment still fail), and \u2014 with --location \u2014 model quota in the target region. Exits non-zero with the exact failing check + remedy. `m8t prereqs` runs the same substrate checks on their own.",
28932
29455
  examples: [
@@ -28935,9 +29458,9 @@ var BootstrapPreflightCommand = class extends M8tCommand {
28935
29458
  ["BYO app registration (directory guests)", "$0 bootstrap preflight --client-id <appId>"]
28936
29459
  ]
28937
29460
  });
28938
- clientId = Option50.String("--client-id");
28939
- subscription = Option50.String("--subscription");
28940
- location = Option50.String("--location", {
29461
+ clientId = Option52.String("--client-id");
29462
+ subscription = Option52.String("--subscription");
29463
+ location = Option52.String("--location", {
28941
29464
  description: "Target region. Enables the model-quota check \u2014 without it, quota is not verified."
28942
29465
  });
28943
29466
  async executeCommand() {
@@ -29034,10 +29557,10 @@ ${colors.error(" " + why)}
29034
29557
  }
29035
29558
 
29036
29559
  // src/commands/bootstrap/launch.ts
29037
- import * as fs30 from "fs";
29038
- import * as os14 from "os";
29039
- import * as path33 from "path";
29040
- import { Command as Command54, Option as Option51 } from "clipanion";
29560
+ import * as fs35 from "fs";
29561
+ import * as os15 from "os";
29562
+ import * as path38 from "path";
29563
+ import { Command as Command56, Option as Option53 } from "clipanion";
29041
29564
  init_errors();
29042
29565
 
29043
29566
  // src/lib/bootstrap-mi.ts
@@ -29192,15 +29715,15 @@ async function kickInstaller(s) {
29192
29715
  }
29193
29716
 
29194
29717
  // src/lib/bootstrap-status.ts
29195
- import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
29196
- import * as fs28 from "fs/promises";
29197
- import * as os12 from "os";
29198
- import * as path31 from "path";
29718
+ import { createHash as createHash5, randomUUID as randomUUID2 } from "crypto";
29719
+ import * as fs33 from "fs/promises";
29720
+ import * as os13 from "os";
29721
+ import * as path36 from "path";
29199
29722
  init_errors();
29200
29723
  var STATUS_CONTAINER = "status";
29201
29724
  var STATUS_BLOB = "status.json";
29202
29725
  function deriveStatusSaName(resourceGroup, subscriptionId) {
29203
- const hex = createHash4("sha256").update(resourceGroup + subscriptionId).digest("hex").slice(0, 12);
29726
+ const hex = createHash5("sha256").update(resourceGroup + subscriptionId).digest("hex").slice(0, 12);
29204
29727
  return `m8tinst${hex}`;
29205
29728
  }
29206
29729
  function statusBlobUrl(saName) {
@@ -29234,7 +29757,7 @@ async function readStatusBlob(opts) {
29234
29757
  cause: e
29235
29758
  });
29236
29759
  }
29237
- const tmpFile = path31.join(os12.tmpdir(), `m8t-status-${randomUUID2()}.json`);
29760
+ const tmpFile = path36.join(os13.tmpdir(), `m8t-status-${randomUUID2()}.json`);
29238
29761
  try {
29239
29762
  await runAz([
29240
29763
  "storage",
@@ -29253,7 +29776,7 @@ async function readStatusBlob(opts) {
29253
29776
  "--no-progress",
29254
29777
  "--only-show-errors"
29255
29778
  ]);
29256
- const raw = await fs28.readFile(tmpFile, "utf8");
29779
+ const raw = await fs33.readFile(tmpFile, "utf8");
29257
29780
  return JSON.parse(raw.trim());
29258
29781
  } catch (e) {
29259
29782
  throw new LocalCliError({
@@ -29263,34 +29786,34 @@ async function readStatusBlob(opts) {
29263
29786
  cause: e
29264
29787
  });
29265
29788
  } finally {
29266
- await fs28.rm(tmpFile, { force: true });
29789
+ await fs33.rm(tmpFile, { force: true });
29267
29790
  }
29268
29791
  }
29269
29792
 
29270
29793
  // src/lib/bootstrap-state.ts
29271
- import * as fs29 from "fs/promises";
29272
- import * as os13 from "os";
29273
- import * as path32 from "path";
29794
+ import * as fs34 from "fs/promises";
29795
+ import * as os14 from "os";
29796
+ import * as path37 from "path";
29274
29797
  function stateDir(home) {
29275
- return path32.join(home, ".m8t");
29798
+ return path37.join(home, ".m8t");
29276
29799
  }
29277
29800
  function statePath(home) {
29278
- return path32.join(stateDir(home), "bootstrap.json");
29801
+ return path37.join(stateDir(home), "bootstrap.json");
29279
29802
  }
29280
- async function readBootstrapState(home = os13.homedir()) {
29803
+ async function readBootstrapState(home = os14.homedir()) {
29281
29804
  try {
29282
- const raw = await fs29.readFile(statePath(home), "utf8");
29805
+ const raw = await fs34.readFile(statePath(home), "utf8");
29283
29806
  return JSON.parse(raw);
29284
29807
  } catch (e) {
29285
29808
  if (e.code === "ENOENT") return null;
29286
29809
  throw e;
29287
29810
  }
29288
29811
  }
29289
- async function writeBootstrapState(state, home = os13.homedir()) {
29290
- await fs29.mkdir(stateDir(home), { recursive: true });
29812
+ async function writeBootstrapState(state, home = os14.homedir()) {
29813
+ await fs34.mkdir(stateDir(home), { recursive: true });
29291
29814
  const tmp = `${statePath(home)}.tmp`;
29292
- await fs29.writeFile(tmp, JSON.stringify(state, null, 2), "utf8");
29293
- await fs29.rename(tmp, statePath(home));
29815
+ await fs34.writeFile(tmp, JSON.stringify(state, null, 2), "utf8");
29816
+ await fs34.rename(tmp, statePath(home));
29294
29817
  }
29295
29818
 
29296
29819
  // src/lib/bootstrap-occupancy.ts
@@ -29402,12 +29925,12 @@ ${colors.error("\u2717")} The GitHub App on disk is installed on ${colors.field(
29402
29925
  // src/commands/bootstrap/launch.ts
29403
29926
  var DEFAULT_RG = "rg-m8t-stack";
29404
29927
  var DEFAULT_INSTALLER = "ghcr.io/m8t-labs/m8t-installer";
29405
- var DEFAULT_INSTALLER_TAG = "v0.1.57";
29928
+ var DEFAULT_INSTALLER_TAG = "v0.1.58";
29406
29929
  var ACI_NAME = "m8t-installer";
29407
29930
  var MI_NAME = "m8t-installer-mi";
29408
29931
  var BootstrapLaunchCommand = class extends M8tCommand {
29409
29932
  static paths = [["bootstrap", "launch"]];
29410
- static usage = Command54.Usage({
29933
+ static usage = Command56.Usage({
29411
29934
  description: "Create + authorize the installer managed identity, then kick the cloud installer.",
29412
29935
  details: "Step 2 of `m8t bootstrap` (run after `preflight`). Ensures the resource group, creates the m8t app registration (or uses --client-id), creates a user-assigned managed identity granted Owner at subscription scope, and launches the published m8t-installer image as an ACI run-to-completion job under that identity. Writes ~/.m8t/bootstrap.json for `status` and `reap`, and threads your Azure object id so the installer can grant you the platform's data-plane roles itself.",
29413
29936
  examples: [
@@ -29418,26 +29941,26 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29418
29941
  ["Share a support contact", "$0 bootstrap launch --location eastus2 --contact-email you@example.com --company 'Acme'"]
29419
29942
  ]
29420
29943
  });
29421
- location = Option51.String("--location");
29422
- resourceGroup = Option51.String("--resource-group");
29423
- clientId = Option51.String("--client-id");
29424
- subscription = Option51.String("--subscription");
29425
- installerTag = Option51.String("--installer-tag");
29944
+ location = Option53.String("--location");
29945
+ resourceGroup = Option53.String("--resource-group");
29946
+ clientId = Option53.String("--client-id");
29947
+ subscription = Option53.String("--subscription");
29948
+ installerTag = Option53.String("--installer-tag");
29426
29949
  // Full image ref override (registry + repo + tag) — an escape hatch when the
29427
29950
  // default org/tag is wrong for the current CLI (e.g. a stale published build).
29428
29951
  // Wins over --installer-tag / the pinned default.
29429
- installerImage = Option51.String("--installer-image");
29430
- gatewayImageRef = Option51.String("--gateway-image-ref");
29431
- githubAppCreds = Option51.String("--github-app-creds");
29432
- contactEmail = Option51.String("--contact-email", { description: "Share a contact email with m8t support. Not sent unless you pass it." });
29433
- company = Option51.String("--company", { description: "Share your company name with m8t support. Not sent unless you pass it." });
29952
+ installerImage = Option53.String("--installer-image");
29953
+ gatewayImageRef = Option53.String("--gateway-image-ref");
29954
+ githubAppCreds = Option53.String("--github-app-creds");
29955
+ contactEmail = Option53.String("--contact-email", { description: "Share a contact email with m8t support. Not sent unless you pass it." });
29956
+ company = Option53.String("--company", { description: "Share your company name with m8t support. Not sent unless you pass it." });
29434
29957
  // Value-carrying on purpose: a bare --force would be cargo-culted into
29435
29958
  // runbooks and harness prompts and erode the protection, whereas a faithful
29436
29959
  // paste can never accidentally carry the victim group's name. It AUTHORIZES
29437
29960
  // the target; --resource-group is what CHOOSES it.
29438
- reinstallInto = Option51.String("--reinstall-into", { description: "Consent to installing into --resource-group even though it already holds resources. Must match the target group's name." });
29439
- org = Option51.String("--org", { description: "Assert the GitHub App on disk is installed on this org; refuses on a mismatch." });
29440
- noBrains = Option51.Boolean("--no-brains", false, { description: "Install without brain-backed workers. For test and CI rigs; the supported install creates brains." });
29961
+ reinstallInto = Option53.String("--reinstall-into", { description: "Consent to installing into --resource-group even though it already holds resources. Must match the target group's name." });
29962
+ org = Option53.String("--org", { description: "Assert the GitHub App on disk is installed on this org; refuses on a mismatch." });
29963
+ noBrains = Option53.Boolean("--no-brains", false, { description: "Install without brain-backed workers. For test and CI rigs; the supported install creates brains." });
29441
29964
  async executeCommand() {
29442
29965
  const location = typeof this.location === "string" ? this.location : void 0;
29443
29966
  if (!location) {
@@ -29476,13 +29999,13 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29476
29999
  `);
29477
30000
  return 0;
29478
30001
  }
29479
- const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path33.join(os14.homedir(), ".m8t", "github-app.json");
30002
+ const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path38.join(os15.homedir(), ".m8t", "github-app.json");
29480
30003
  const skipBrains = this.noBrains === true;
29481
30004
  const requestedOrg = typeof this.org === "string" ? this.org : void 0;
29482
30005
  let githubApp;
29483
30006
  if (skipBrains) {
29484
30007
  out("installing without brain-backed workers; no GitHub App credentials will be used");
29485
- } else if (!fs30.existsSync(credsPath)) {
30008
+ } else if (!fs35.existsSync(credsPath)) {
29486
30009
  this.context.stderr.write(buildMissingCredsRefusal(credsPath));
29487
30010
  throw new LocalCliError({
29488
30011
  code: "GITHUB_APP_CREDS_MISSING",
@@ -29492,7 +30015,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29492
30015
  } else {
29493
30016
  let parsed;
29494
30017
  try {
29495
- parsed = JSON.parse(fs30.readFileSync(credsPath, "utf8"));
30018
+ parsed = JSON.parse(fs35.readFileSync(credsPath, "utf8"));
29496
30019
  } catch {
29497
30020
  throw new LocalCliError({
29498
30021
  code: "GITHUB_APP_CREDS_INVALID",
@@ -29510,7 +30033,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29510
30033
  }
29511
30034
  let pem;
29512
30035
  try {
29513
- pem = fs30.readFileSync(parsed.pemPath, "utf8");
30036
+ pem = fs35.readFileSync(parsed.pemPath, "utf8");
29514
30037
  } catch {
29515
30038
  throw new LocalCliError({
29516
30039
  code: "GITHUB_APP_PEM_MISSING",
@@ -29598,7 +30121,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
29598
30121
  };
29599
30122
 
29600
30123
  // src/commands/bootstrap/status.ts
29601
- import { Command as Command56, Option as Option53 } from "clipanion";
30124
+ import { Command as Command58, Option as Option55 } from "clipanion";
29602
30125
  init_errors();
29603
30126
 
29604
30127
  // src/lib/bootstrap-aci-state.ts
@@ -29624,15 +30147,15 @@ async function getAciState(opts) {
29624
30147
  }
29625
30148
 
29626
30149
  // src/lib/bootstrap-finalize.ts
29627
- import * as fs34 from "fs/promises";
29628
- import * as os18 from "os";
29629
- import * as path39 from "path";
30150
+ import * as fs39 from "fs/promises";
30151
+ import * as os19 from "os";
30152
+ import * as path44 from "path";
29630
30153
 
29631
30154
  // src/lib/company-profile-seed.ts
29632
30155
  import { spawn as spawn6 } from "child_process";
29633
- import { closeSync, openSync, readFileSync as readFileSync22 } from "fs";
29634
- import * as os15 from "os";
29635
- import * as path34 from "path";
30156
+ import { closeSync, openSync, readFileSync as readFileSync25 } from "fs";
30157
+ import * as os16 from "os";
30158
+ import * as path39 from "path";
29636
30159
  init_errors();
29637
30160
 
29638
30161
  // src/lib/onboarding-profile.ts
@@ -30357,9 +30880,9 @@ function composeFounderIdentityNote(id) {
30357
30880
 
30358
30881
  // src/lib/company-profile-seed.ts
30359
30882
  function readGithubAppCreds(credsPath) {
30360
- const p = credsPath ?? path34.join(os15.homedir(), ".m8t", "github-app.json");
30883
+ const p = credsPath ?? path39.join(os16.homedir(), ".m8t", "github-app.json");
30361
30884
  try {
30362
- return JSON.parse(readFileSync22(p, "utf8"));
30885
+ return JSON.parse(readFileSync25(p, "utf8"));
30363
30886
  } catch {
30364
30887
  return null;
30365
30888
  }
@@ -30425,7 +30948,7 @@ function upsertMemoryIndexOnce(existing, line2, targetPath2) {
30425
30948
  async function applyProfileToBrain(args) {
30426
30949
  const token = await mintInstallationTokenFromPem({
30427
30950
  appId: args.appCreds.appId,
30428
- privateKeyPem: readFileSync22(args.appCreds.pemPath, "utf8"),
30951
+ privateKeyPem: readFileSync25(args.appCreds.pemPath, "utf8"),
30429
30952
  installationId: args.appCreds.installationId,
30430
30953
  fetchImpl: args.fetchImpl
30431
30954
  });
@@ -30515,7 +31038,7 @@ async function applyProfileToBrains(args) {
30515
31038
  }
30516
31039
  }
30517
31040
  function spawnDetachedSeedWatch() {
30518
- const logPath = path34.join(os15.homedir(), ".m8t", "seed-profile.log");
31041
+ const logPath = path39.join(os16.homedir(), ".m8t", "seed-profile.log");
30519
31042
  const fd = openSync(logPath, "a");
30520
31043
  try {
30521
31044
  const child = spawn6(process.execPath, [process.argv[1] ?? "", "bootstrap", "seed-profile", "--watch"], {
@@ -30589,16 +31112,16 @@ function renderInstallSummary(args) {
30589
31112
 
30590
31113
  // src/lib/companion-install.ts
30591
31114
  import { constants as constants2 } from "fs";
30592
- import * as fs32 from "fs/promises";
30593
- import * as path36 from "path";
31115
+ import * as fs37 from "fs/promises";
31116
+ import * as path41 from "path";
30594
31117
  import { randomUUID as randomUUID3 } from "crypto";
30595
31118
  import { execFile, spawn as spawn7 } from "child_process";
30596
31119
 
30597
31120
  // src/lib/companion-artifact.ts
30598
- import { createHash as createHash5 } from "crypto";
31121
+ import { createHash as createHash6 } from "crypto";
30599
31122
  import { constants } from "fs";
30600
- import * as fs31 from "fs/promises";
30601
- import * as path35 from "path";
31123
+ import * as fs36 from "fs/promises";
31124
+ import * as path40 from "path";
30602
31125
  var SHA256 = /^[a-f0-9]{64}$/u;
30603
31126
  var VERSION2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/u;
30604
31127
  function exactKeys(value, expected) {
@@ -30606,23 +31129,23 @@ function exactKeys(value, expected) {
30606
31129
  return actual.length === expected.length && actual.every((key2, index) => key2 === [...expected].sort()[index]);
30607
31130
  }
30608
31131
  function normalizedRelative(value) {
30609
- if (value.length === 0 || value.includes("\\") || value.includes("\0") || path35.posix.isAbsolute(value)) {
31132
+ if (value.length === 0 || value.includes("\\") || value.includes("\0") || path40.posix.isAbsolute(value)) {
30610
31133
  throw new Error("Artifact path must be a normalized relative POSIX path");
30611
31134
  }
30612
- const normalized = path35.posix.normalize(value);
31135
+ const normalized = path40.posix.normalize(value);
30613
31136
  if (normalized !== value || normalized === "." || normalized === ".." || normalized.startsWith("../")) {
30614
31137
  throw new Error("Artifact path escapes the payload root");
30615
31138
  }
30616
31139
  return value;
30617
31140
  }
30618
31141
  function validateLink(entryPath, target) {
30619
- if (target.length === 0 || target.includes("\\") || target.includes("\0") || path35.posix.isAbsolute(target)) {
31142
+ if (target.length === 0 || target.includes("\\") || target.includes("\0") || path40.posix.isAbsolute(target)) {
30620
31143
  throw new Error("Artifact symlink target must be relative");
30621
31144
  }
30622
- const resolved = path35.posix.normalize(
30623
- path35.posix.join(path35.posix.dirname(entryPath), target)
31145
+ const resolved = path40.posix.normalize(
31146
+ path40.posix.join(path40.posix.dirname(entryPath), target)
30624
31147
  );
30625
- if (resolved === ".." || resolved.startsWith("../") || path35.posix.isAbsolute(resolved)) {
31148
+ if (resolved === ".." || resolved.startsWith("../") || path40.posix.isAbsolute(resolved)) {
30626
31149
  throw new Error("Artifact symlink target escapes the payload root");
30627
31150
  }
30628
31151
  return target;
@@ -30633,7 +31156,7 @@ function canonicalEntry(entry) {
30633
31156
  `;
30634
31157
  }
30635
31158
  function artifactTreeSha256(entries) {
30636
- const hash = createHash5("sha256");
31159
+ const hash = createHash6("sha256");
30637
31160
  const ordered = [...entries].sort(
30638
31161
  (left, right) => left.path.localeCompare(right.path)
30639
31162
  );
@@ -30703,19 +31226,19 @@ function parseArtifactManifest(value) {
30703
31226
  };
30704
31227
  }
30705
31228
  async function sha256File2(filePath) {
30706
- return createHash5("sha256").update(await fs31.readFile(filePath)).digest("hex");
31229
+ return createHash6("sha256").update(await fs36.readFile(filePath)).digest("hex");
30707
31230
  }
30708
- async function walk(root, relative3 = "") {
30709
- const directory = path35.join(root, ...relative3.split("/").filter(Boolean));
30710
- const children = await fs31.readdir(directory, { withFileTypes: true });
31231
+ async function walk2(root, relative4 = "") {
31232
+ const directory = path40.join(root, ...relative4.split("/").filter(Boolean));
31233
+ const children = await fs36.readdir(directory, { withFileTypes: true });
30711
31234
  const entries = [];
30712
31235
  for (const child of children.sort((left, right) => left.name.localeCompare(right.name))) {
30713
- const childRelative = relative3 ? `${relative3}/${child.name}` : child.name;
31236
+ const childRelative = relative4 ? `${relative4}/${child.name}` : child.name;
30714
31237
  normalizedRelative(childRelative);
30715
- const childPath = path35.join(directory, child.name);
30716
- const stat5 = await fs31.lstat(childPath);
31238
+ const childPath = path40.join(directory, child.name);
31239
+ const stat5 = await fs36.lstat(childPath);
30717
31240
  if (stat5.isDirectory()) {
30718
- entries.push(...await walk(root, childRelative));
31241
+ entries.push(...await walk2(root, childRelative));
30719
31242
  } else if (stat5.isFile()) {
30720
31243
  entries.push({
30721
31244
  type: "file",
@@ -30725,7 +31248,7 @@ async function walk(root, relative3 = "") {
30725
31248
  sha256: await sha256File2(childPath)
30726
31249
  });
30727
31250
  } else if (stat5.isSymbolicLink()) {
30728
- const target = await fs31.readlink(childPath);
31251
+ const target = await fs36.readlink(childPath);
30729
31252
  entries.push({
30730
31253
  type: "symlink",
30731
31254
  path: childRelative,
@@ -30738,19 +31261,19 @@ async function walk(root, relative3 = "") {
30738
31261
  return entries;
30739
31262
  }
30740
31263
  async function ensureRealDirectory(root) {
30741
- const stat5 = await fs31.lstat(root);
31264
+ const stat5 = await fs36.lstat(root);
30742
31265
  if (stat5.isSymbolicLink()) throw new Error("Artifact root is a symbolic link");
30743
31266
  if (!stat5.isDirectory()) throw new Error("Artifact root is not a directory");
30744
31267
  }
30745
31268
  async function validateResolvedLinks(root, entries) {
30746
- const realRoot = await fs31.realpath(root);
31269
+ const realRoot = await fs36.realpath(root);
30747
31270
  for (const entry of entries) {
30748
31271
  if (entry.type !== "symlink") continue;
30749
31272
  try {
30750
- const linkPath = path35.join(root, ...entry.path.split("/"));
30751
- const resolved = await fs31.realpath(linkPath);
30752
- const relative3 = path35.relative(realRoot, resolved);
30753
- if (relative3 === ".." || relative3.startsWith(`..${path35.sep}`) || path35.isAbsolute(relative3)) {
31273
+ const linkPath = path40.join(root, ...entry.path.split("/"));
31274
+ const resolved = await fs36.realpath(linkPath);
31275
+ const relative4 = path40.relative(realRoot, resolved);
31276
+ if (relative4 === ".." || relative4.startsWith(`..${path40.sep}`) || path40.isAbsolute(relative4)) {
30754
31277
  throw new Error("Artifact symlink chain escapes the payload root");
30755
31278
  }
30756
31279
  } catch (error) {
@@ -30763,7 +31286,7 @@ async function validateResolvedLinks(root, entries) {
30763
31286
  }
30764
31287
  async function buildArtifactManifest(payloadRoot, input) {
30765
31288
  await ensureRealDirectory(payloadRoot);
30766
- const entries = await walk(payloadRoot);
31289
+ const entries = await walk2(payloadRoot);
30767
31290
  await validateResolvedLinks(payloadRoot, entries);
30768
31291
  const manifest = {
30769
31292
  schemaVersion: 1,
@@ -30780,13 +31303,13 @@ async function buildArtifactManifest(payloadRoot, input) {
30780
31303
  return manifest;
30781
31304
  }
30782
31305
  async function readArtifactManifest(manifestPath) {
30783
- const before = await fs31.lstat(manifestPath);
31306
+ const before = await fs36.lstat(manifestPath);
30784
31307
  if (before.isSymbolicLink() || !before.isFile()) {
30785
31308
  throw new Error("Artifact manifest is a symbolic link or non-file");
30786
31309
  }
30787
31310
  let handle;
30788
31311
  try {
30789
- handle = await fs31.open(
31312
+ handle = await fs36.open(
30790
31313
  manifestPath,
30791
31314
  constants.O_RDONLY | constants.O_NOFOLLOW
30792
31315
  );
@@ -30803,16 +31326,16 @@ async function readArtifactManifest(manifestPath) {
30803
31326
  }
30804
31327
  }
30805
31328
  function ensureContainedEntry(root, entryPath) {
30806
- const absolute = path35.join(root, ...entryPath.split("/"));
30807
- const relative3 = path35.relative(root, absolute);
30808
- if (relative3.startsWith("..") || path35.isAbsolute(relative3)) {
31329
+ const absolute = path40.join(root, ...entryPath.split("/"));
31330
+ const relative4 = path40.relative(root, absolute);
31331
+ if (relative4.startsWith("..") || path40.isAbsolute(relative4)) {
30809
31332
  throw new Error("Artifact entry escapes payload root");
30810
31333
  }
30811
31334
  return absolute;
30812
31335
  }
30813
31336
  async function verifyArtifactSource(payloadRoot, manifest) {
30814
31337
  await ensureRealDirectory(payloadRoot);
30815
- const actual = await walk(payloadRoot);
31338
+ const actual = await walk2(payloadRoot);
30816
31339
  await validateResolvedLinks(payloadRoot, actual);
30817
31340
  const declared = new Map(manifest.entries.map((entry) => [entry.path, entry]));
30818
31341
  for (const entry of actual) {
@@ -30829,7 +31352,7 @@ async function verifyArtifactSource(payloadRoot, manifest) {
30829
31352
  }
30830
31353
  async function verifyArtifactPayload(payloadRoot, manifest) {
30831
31354
  await ensureRealDirectory(payloadRoot);
30832
- const actual = await walk(payloadRoot);
31355
+ const actual = await walk2(payloadRoot);
30833
31356
  await validateResolvedLinks(payloadRoot, actual);
30834
31357
  if (actual.length !== manifest.entries.length || artifactTreeSha256(actual) !== manifest.treeSha256) {
30835
31358
  throw new Error("Artifact payload digest or size does not match manifest");
@@ -30844,27 +31367,27 @@ async function verifyArtifactPayload(payloadRoot, manifest) {
30844
31367
  async function copyArtifactPayload(sourceRoot, targetRoot, manifest) {
30845
31368
  await verifyArtifactSource(sourceRoot, manifest);
30846
31369
  try {
30847
- const targetStat = await fs31.lstat(targetRoot);
31370
+ const targetStat = await fs36.lstat(targetRoot);
30848
31371
  if (targetStat.isSymbolicLink()) {
30849
31372
  throw new Error("Install target is a symbolic link");
30850
31373
  }
30851
31374
  if (!targetStat.isDirectory()) throw new Error("Install target is not a directory");
30852
- if ((await fs31.readdir(targetRoot)).length > 0) {
31375
+ if ((await fs36.readdir(targetRoot)).length > 0) {
30853
31376
  throw new Error("Install staging target is not empty");
30854
31377
  }
30855
31378
  } catch (error) {
30856
31379
  if (error.code !== "ENOENT") throw error;
30857
- await fs31.mkdir(targetRoot, { recursive: false, mode: 448 });
31380
+ await fs36.mkdir(targetRoot, { recursive: false, mode: 448 });
30858
31381
  }
30859
31382
  for (const entry of manifest.entries) {
30860
31383
  const source = ensureContainedEntry(sourceRoot, entry.path);
30861
31384
  const target = ensureContainedEntry(targetRoot, entry.path);
30862
- await fs31.mkdir(path35.dirname(target), { recursive: true, mode: 448 });
31385
+ await fs36.mkdir(path40.dirname(target), { recursive: true, mode: 448 });
30863
31386
  if (entry.type === "file") {
30864
- await fs31.copyFile(source, target);
30865
- await fs31.chmod(target, entry.mode);
31387
+ await fs36.copyFile(source, target);
31388
+ await fs36.chmod(target, entry.mode);
30866
31389
  } else {
30867
- await fs31.symlink(entry.target, target);
31390
+ await fs36.symlink(entry.target, target);
30868
31391
  }
30869
31392
  }
30870
31393
  await verifyArtifactPayload(targetRoot, manifest);
@@ -30881,39 +31404,39 @@ function commandError(error, message) {
30881
31404
  return wrapped;
30882
31405
  }
30883
31406
  function execFileAsync(file, args) {
30884
- return new Promise((resolve4, reject) => {
31407
+ return new Promise((resolve6, reject) => {
30885
31408
  execFile(file, [...args], { windowsHide: true }, (error) => {
30886
31409
  if (error) reject(commandError(error, "Login-item command failed"));
30887
- else resolve4();
31410
+ else resolve6();
30888
31411
  });
30889
31412
  });
30890
31413
  }
30891
31414
  function execFileOutput(file, args) {
30892
- return new Promise((resolve4, reject) => {
31415
+ return new Promise((resolve6, reject) => {
30893
31416
  execFile(
30894
31417
  file,
30895
31418
  [...args],
30896
31419
  { windowsHide: true },
30897
31420
  (error, stdout) => {
30898
31421
  if (error) reject(commandError(error, "Login-item query failed"));
30899
- else resolve4(stdout);
31422
+ else resolve6(stdout);
30900
31423
  }
30901
31424
  );
30902
31425
  });
30903
31426
  }
30904
31427
  async function setCompanionStartAtLogin(input) {
30905
31428
  if (input.platform === "darwin") {
30906
- const launchAgents = path36.join(input.homeDirectory, "Library", "LaunchAgents");
30907
- const registration = path36.join(
31429
+ const launchAgents = path41.join(input.homeDirectory, "Library", "LaunchAgents");
31430
+ const registration = path41.join(
30908
31431
  launchAgents,
30909
31432
  "com.m8t.companion.plist"
30910
31433
  );
30911
31434
  await assertNotSymlink(registration, "Start-at-login registration");
30912
31435
  if (!input.enabled) {
30913
- await fs32.rm(registration, { force: true });
31436
+ await fs37.rm(registration, { force: true });
30914
31437
  return;
30915
31438
  }
30916
- await fs32.mkdir(launchAgents, { recursive: true, mode: 448 });
31439
+ await fs37.mkdir(launchAgents, { recursive: true, mode: 448 });
30917
31440
  const plist = '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0"><dict><key>Label</key><string>com.m8t.companion</string><key>ProgramArguments</key><array><string>' + xmlEscape(input.executable) + "</string></array><key>RunAtLoad</key><true/></dict></plist>\n";
30918
31441
  await atomicWriteText(registration, plist, 384);
30919
31442
  return;
@@ -30965,7 +31488,7 @@ async function setCompanionStartAtLogin(input) {
30965
31488
  }
30966
31489
  async function getCompanionStartAtLogin(input) {
30967
31490
  if (input.platform === "darwin") {
30968
- const registration = path36.join(
31491
+ const registration = path41.join(
30969
31492
  input.homeDirectory,
30970
31493
  "Library",
30971
31494
  "LaunchAgents",
@@ -31027,26 +31550,26 @@ function assertSupported(options) {
31027
31550
  }
31028
31551
  function companionInstallPaths(options) {
31029
31552
  assertSupported(options);
31030
- const companionState = path36.join(
31553
+ const companionState = path41.join(
31031
31554
  options.homeDirectory,
31032
31555
  ".m8t",
31033
31556
  "companion"
31034
31557
  );
31035
- const targetRoot = options.platform === "darwin" ? path36.join(
31558
+ const targetRoot = options.platform === "darwin" ? path41.join(
31036
31559
  options.homeDirectory,
31037
31560
  "Applications",
31038
31561
  "m8t Companion.app"
31039
- ) : path36.join(
31040
- options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local"),
31562
+ ) : path41.join(
31563
+ options.localAppData ?? path41.join(options.homeDirectory, "AppData", "Local"),
31041
31564
  "m8t",
31042
31565
  "companion",
31043
31566
  "app"
31044
31567
  );
31045
31568
  return {
31046
31569
  targetRoot,
31047
- installManifest: path36.join(companionState, "install-v1.json"),
31048
- runtimeBinding: path36.join(companionState, "runtime-v1.json"),
31049
- preferences: path36.join(companionState, "preferences-v1.json")
31570
+ installManifest: path41.join(companionState, "install-v1.json"),
31571
+ runtimeBinding: path41.join(companionState, "runtime-v1.json"),
31572
+ preferences: path41.join(companionState, "preferences-v1.json")
31050
31573
  };
31051
31574
  }
31052
31575
  function exactKeys2(value, keys) {
@@ -31057,7 +31580,7 @@ function parseInstallManifest(value) {
31057
31580
  throw new Error("Install manifest schema is invalid");
31058
31581
  }
31059
31582
  const record = value;
31060
- 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)) {
31583
+ 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" || !path41.isAbsolute(record.ownedTargetRoot)) {
31061
31584
  throw new Error("Install manifest schema is invalid");
31062
31585
  }
31063
31586
  return record;
@@ -31067,7 +31590,7 @@ function parseRuntimeBinding(value, platform) {
31067
31590
  throw new Error("Runtime binding schema is invalid");
31068
31591
  }
31069
31592
  const record = value;
31070
- const paths = platform === "win32" ? path36.win32 : path36.posix;
31593
+ const paths = platform === "win32" ? path41.win32 : path41.posix;
31071
31594
  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") {
31072
31595
  throw new Error("Runtime binding schema is invalid");
31073
31596
  }
@@ -31092,7 +31615,7 @@ function validateGatewayOrigin(value) {
31092
31615
  }
31093
31616
  async function assertNotSymlink(filePath, kind) {
31094
31617
  try {
31095
- if ((await fs32.lstat(filePath)).isSymbolicLink()) {
31618
+ if ((await fs37.lstat(filePath)).isSymbolicLink()) {
31096
31619
  throw new Error(`${kind} is a symbolic link`);
31097
31620
  }
31098
31621
  } catch (error) {
@@ -31101,20 +31624,20 @@ async function assertNotSymlink(filePath, kind) {
31101
31624
  }
31102
31625
  }
31103
31626
  async function assertOwnedDirectoryChain(anchor, targetDirectory) {
31104
- const relative3 = path36.relative(anchor, targetDirectory);
31105
- if (relative3 === ".." || relative3.startsWith(`..${path36.sep}`) || path36.isAbsolute(relative3)) {
31627
+ const relative4 = path41.relative(anchor, targetDirectory);
31628
+ if (relative4 === ".." || relative4.startsWith(`..${path41.sep}`) || path41.isAbsolute(relative4)) {
31106
31629
  throw new Error("Companion owned directory escapes its trusted anchor");
31107
31630
  }
31108
- const segments = relative3.split(path36.sep).filter(Boolean);
31631
+ const segments = relative4.split(path41.sep).filter(Boolean);
31109
31632
  let current = anchor;
31110
- const anchorStatus = await fs32.lstat(anchor);
31633
+ const anchorStatus = await fs37.lstat(anchor);
31111
31634
  if (anchorStatus.isSymbolicLink() || !anchorStatus.isDirectory()) {
31112
31635
  throw new Error("Companion owned directory anchor is unsafe");
31113
31636
  }
31114
31637
  for (const segment of segments) {
31115
- current = path36.join(current, segment);
31638
+ current = path41.join(current, segment);
31116
31639
  try {
31117
- const status = await fs32.lstat(current);
31640
+ const status = await fs37.lstat(current);
31118
31641
  if (status.isSymbolicLink() || !status.isDirectory()) {
31119
31642
  throw new Error("Companion owned directory contains a symbolic link");
31120
31643
  }
@@ -31127,19 +31650,19 @@ async function assertOwnedDirectoryChain(anchor, targetDirectory) {
31127
31650
  async function assertOwnedParents(options, paths) {
31128
31651
  await assertOwnedDirectoryChain(
31129
31652
  options.homeDirectory,
31130
- path36.dirname(paths.installManifest)
31653
+ path41.dirname(paths.installManifest)
31131
31654
  );
31132
- const targetAnchor = options.platform === "win32" ? options.localAppData ?? path36.join(options.homeDirectory, "AppData", "Local") : options.homeDirectory;
31133
- await assertOwnedDirectoryChain(targetAnchor, path36.dirname(paths.targetRoot));
31655
+ const targetAnchor = options.platform === "win32" ? options.localAppData ?? path41.join(options.homeDirectory, "AppData", "Local") : options.homeDirectory;
31656
+ await assertOwnedDirectoryChain(targetAnchor, path41.dirname(paths.targetRoot));
31134
31657
  }
31135
31658
  async function readRegularText(filePath, maxBytes) {
31136
- const before = await fs32.lstat(filePath);
31659
+ const before = await fs37.lstat(filePath);
31137
31660
  if (before.isSymbolicLink() || !before.isFile()) {
31138
31661
  throw new Error("Companion state file is not a regular file");
31139
31662
  }
31140
31663
  let handle;
31141
31664
  try {
31142
- handle = await fs32.open(
31665
+ handle = await fs37.open(
31143
31666
  filePath,
31144
31667
  constants2.O_RDONLY | constants2.O_NOFOLLOW
31145
31668
  );
@@ -31162,27 +31685,27 @@ async function atomicWriteJson(filePath, value) {
31162
31685
  }
31163
31686
  async function atomicWriteText(filePath, contents, mode) {
31164
31687
  await assertNotSymlink(filePath, "Companion state file");
31165
- await fs32.mkdir(path36.dirname(filePath), {
31688
+ await fs37.mkdir(path41.dirname(filePath), {
31166
31689
  recursive: true,
31167
31690
  mode: 448
31168
31691
  });
31169
31692
  const temporary = `${filePath}.${randomUUID3()}.tmp`;
31170
31693
  try {
31171
- await fs32.writeFile(temporary, contents, {
31694
+ await fs37.writeFile(temporary, contents, {
31172
31695
  mode,
31173
31696
  flag: "wx"
31174
31697
  });
31175
- await fs32.rename(temporary, filePath);
31176
- await fs32.chmod(filePath, mode).catch(() => void 0);
31698
+ await fs37.rename(temporary, filePath);
31699
+ await fs37.chmod(filePath, mode).catch(() => void 0);
31177
31700
  } finally {
31178
- await fs32.rm(temporary, { force: true }).catch(() => void 0);
31701
+ await fs37.rm(temporary, { force: true }).catch(() => void 0);
31179
31702
  }
31180
31703
  }
31181
31704
  async function realRegularFile(filePath, executable) {
31182
- const real = await fs32.realpath(filePath);
31183
- const stat5 = await fs32.stat(real);
31705
+ const real = await fs37.realpath(filePath);
31706
+ const stat5 = await fs37.stat(real);
31184
31707
  if (!stat5.isFile()) throw new Error("Companion launch target is not a file");
31185
- await fs32.access(real, executable ? constants2.X_OK : constants2.R_OK);
31708
+ await fs37.access(real, executable ? constants2.X_OK : constants2.R_OK);
31186
31709
  return real;
31187
31710
  }
31188
31711
  function defaultLaunch(executable) {
@@ -31198,7 +31721,7 @@ async function companionIsRunning(platform, executable) {
31198
31721
  if (platform !== "win32") return false;
31199
31722
  let handle;
31200
31723
  try {
31201
- handle = await fs32.open(executable, "r+");
31724
+ handle = await fs37.open(executable, "r+");
31202
31725
  } catch (error) {
31203
31726
  const code = error.code;
31204
31727
  if (code === "ENOENT") return false;
@@ -31279,7 +31802,7 @@ async function statusCompanion(options) {
31279
31802
  realRegularFile(runtime.nodeExecutable, options.platform !== "win32"),
31280
31803
  realRegularFile(runtime.cliEntry, false)
31281
31804
  ]);
31282
- const executable = path36.join(
31805
+ const executable = path41.join(
31283
31806
  paths.targetRoot,
31284
31807
  ...install.entryRelativePath.split("/")
31285
31808
  );
@@ -31312,7 +31835,7 @@ async function snapshotFile(filePath) {
31312
31835
  }
31313
31836
  async function restoreFile(filePath, bytes) {
31314
31837
  if (bytes === null) {
31315
- await fs32.rm(filePath, { force: true });
31838
+ await fs37.rm(filePath, { force: true });
31316
31839
  } else {
31317
31840
  await atomicWriteJson(filePath, JSON.parse(bytes.toString("utf8")));
31318
31841
  }
@@ -31327,8 +31850,8 @@ async function converge(options, force) {
31327
31850
  if (artifactManifest.platform !== options.platform || artifactManifest.architecture !== options.architecture) {
31328
31851
  throw new Error("Companion artifact does not match this OS and architecture");
31329
31852
  }
31330
- const payloadRoot = path36.join(
31331
- path36.dirname(options.artifactManifestPath),
31853
+ const payloadRoot = path41.join(
31854
+ path41.dirname(options.artifactManifestPath),
31332
31855
  "payload"
31333
31856
  );
31334
31857
  await verifyArtifactSource(payloadRoot, artifactManifest);
@@ -31348,7 +31871,7 @@ async function converge(options, force) {
31348
31871
  if (priorInstalled) {
31349
31872
  await assertCompanionNotRunning(
31350
31873
  options,
31351
- path36.join(
31874
+ path41.join(
31352
31875
  priorInstalled.paths.targetRoot,
31353
31876
  ...priorInstalled.install.entryRelativePath.split("/")
31354
31877
  )
@@ -31356,7 +31879,7 @@ async function converge(options, force) {
31356
31879
  }
31357
31880
  if (current.state === "not-installed") {
31358
31881
  try {
31359
- await fs32.lstat(paths.targetRoot);
31882
+ await fs37.lstat(paths.targetRoot);
31360
31883
  throw new Error(
31361
31884
  "The fixed companion target exists without an owned install manifest"
31362
31885
  );
@@ -31367,7 +31890,7 @@ async function converge(options, force) {
31367
31890
  const stage = `${paths.targetRoot}.m8t-stage-${randomUUID3()}`;
31368
31891
  const backup = `${paths.targetRoot}.m8t-backup-${randomUUID3()}`;
31369
31892
  const copy = options.copyPayload ?? copyArtifactPayload;
31370
- await fs32.mkdir(path36.dirname(paths.targetRoot), {
31893
+ await fs37.mkdir(path41.dirname(paths.targetRoot), {
31371
31894
  recursive: true,
31372
31895
  mode: 448
31373
31896
  });
@@ -31384,12 +31907,12 @@ async function converge(options, force) {
31384
31907
  try {
31385
31908
  await copy(payloadRoot, stage, artifactManifest);
31386
31909
  try {
31387
- await fs32.rename(paths.targetRoot, backup);
31910
+ await fs37.rename(paths.targetRoot, backup);
31388
31911
  movedPrior = true;
31389
31912
  } catch (error) {
31390
31913
  if (error.code !== "ENOENT") throw error;
31391
31914
  }
31392
- await fs32.rename(stage, paths.targetRoot);
31915
+ await fs37.rename(stage, paths.targetRoot);
31393
31916
  installedStage = true;
31394
31917
  const nodeExecutable = await realRegularFile(
31395
31918
  options.nodeExecutable,
@@ -31431,7 +31954,7 @@ async function converge(options, force) {
31431
31954
  await readClosedJson(paths.runtimeBinding),
31432
31955
  options.platform
31433
31956
  );
31434
- const executable = path36.join(
31957
+ const executable = path41.join(
31435
31958
  paths.targetRoot,
31436
31959
  ...artifactManifest.entryRelativePath.split("/")
31437
31960
  );
@@ -31441,7 +31964,7 @@ async function converge(options, force) {
31441
31964
  platform: options.platform,
31442
31965
  executable: ownedExecutable
31443
31966
  }));
31444
- priorLoginExecutable = priorInstalled ? path36.join(
31967
+ priorLoginExecutable = priorInstalled ? path41.join(
31445
31968
  priorInstalled.paths.targetRoot,
31446
31969
  ...priorInstalled.install.entryRelativePath.split("/")
31447
31970
  ) : executable;
@@ -31452,7 +31975,7 @@ async function converge(options, force) {
31452
31975
  );
31453
31976
  loginChanged = true;
31454
31977
  await (options.launch ?? defaultLaunch)(executable);
31455
- await fs32.rm(backup, { recursive: true, force: true });
31978
+ await fs37.rm(backup, { recursive: true, force: true });
31456
31979
  return {
31457
31980
  state: "installed",
31458
31981
  version: artifactManifest.version,
@@ -31466,15 +31989,15 @@ async function converge(options, force) {
31466
31989
  () => void 0
31467
31990
  );
31468
31991
  }
31469
- await fs32.rm(stage, { recursive: true, force: true }).catch(() => void 0);
31992
+ await fs37.rm(stage, { recursive: true, force: true }).catch(() => void 0);
31470
31993
  if (installedStage) {
31471
- await fs32.rm(paths.targetRoot, {
31994
+ await fs37.rm(paths.targetRoot, {
31472
31995
  recursive: true,
31473
31996
  force: true
31474
31997
  }).catch(() => void 0);
31475
31998
  }
31476
31999
  if (movedPrior) {
31477
- await fs32.rename(backup, paths.targetRoot).catch(() => void 0);
32000
+ await fs37.rename(backup, paths.targetRoot).catch(() => void 0);
31478
32001
  }
31479
32002
  await Promise.all([
31480
32003
  restoreFile(paths.installManifest, snapshots[0]),
@@ -31500,14 +32023,14 @@ async function uninstallCompanion(options) {
31500
32023
  if (install.ownedTargetRoot !== paths.targetRoot) {
31501
32024
  throw new Error("Refusing to remove a non-owned companion target");
31502
32025
  }
31503
- const executable = path36.join(
32026
+ const executable = path41.join(
31504
32027
  paths.targetRoot,
31505
32028
  ...install.entryRelativePath.split("/")
31506
32029
  );
31507
32030
  await assertCompanionNotRunning(options, executable);
31508
32031
  await (options.setStartAtLogin ?? (() => Promise.resolve()))(executable, false);
31509
32032
  const remove = options.removeOwnedPath ?? (async (ownedPath, recursive) => {
31510
- await fs32.rm(ownedPath, { recursive, force: true });
32033
+ await fs37.rm(ownedPath, { recursive, force: true });
31511
32034
  });
31512
32035
  await remove(paths.targetRoot, true);
31513
32036
  await remove(paths.installManifest, false);
@@ -31517,9 +32040,9 @@ async function uninstallCompanion(options) {
31517
32040
  }
31518
32041
 
31519
32042
  // src/commands/companion/install.ts
31520
- import * as os17 from "os";
31521
- import * as path38 from "path";
31522
- import { Command as Command55, Option as Option52 } from "clipanion";
32043
+ import * as os18 from "os";
32044
+ import * as path43 from "path";
32045
+ import { Command as Command57, Option as Option54 } from "clipanion";
31523
32046
 
31524
32047
  // src/lib/companion-channel.ts
31525
32048
  async function readCompanionRelease(source = { url: CHANNEL_LATEST_URL }, deps = {}) {
@@ -31534,18 +32057,18 @@ async function readCompanionRelease(source = { url: CHANNEL_LATEST_URL }, deps =
31534
32057
  }
31535
32058
 
31536
32059
  // src/lib/companion-download.ts
31537
- import { createHash as createHash6 } from "crypto";
32060
+ import { createHash as createHash7 } from "crypto";
31538
32061
  import { execFile as execFile2 } from "child_process";
31539
- import * as fs33 from "fs/promises";
31540
- import * as os16 from "os";
31541
- import * as path37 from "path";
32062
+ import * as fs38 from "fs/promises";
32063
+ import * as os17 from "os";
32064
+ import * as path42 from "path";
31542
32065
  init_errors();
31543
32066
  var MAX_ASSET_BYTES = 512 * 1024 * 1024;
31544
32067
  function extractArchive(archive, into) {
31545
- return new Promise((resolve4, reject) => {
32068
+ return new Promise((resolve6, reject) => {
31546
32069
  execFile2("tar", ["-xzf", archive, "-C", into], { windowsHide: true }, (error) => {
31547
32070
  if (error) reject(new Error(`Could not unpack the companion build: ${error.message}`));
31548
- else resolve4();
32071
+ else resolve6();
31549
32072
  });
31550
32073
  });
31551
32074
  }
@@ -31583,7 +32106,7 @@ async function downloadCompanionArtifact(component, deps = {}) {
31583
32106
  message: `${pinned.asset} is larger than this command will accept.`
31584
32107
  });
31585
32108
  }
31586
- const digest = createHash6("sha256").update(bytes).digest("hex");
32109
+ const digest = createHash7("sha256").update(bytes).digest("hex");
31587
32110
  if (digest !== pinned.sha256) {
31588
32111
  throw new LocalCliError({
31589
32112
  code: "COMPANION_ASSET_DIGEST_MISMATCH",
@@ -31591,20 +32114,20 @@ async function downloadCompanionArtifact(component, deps = {}) {
31591
32114
  hint: "Nothing was unpacked. This is what a corrupted download or a substituted file looks like \u2014 retry, and report it if it persists."
31592
32115
  });
31593
32116
  }
31594
- const root = await (deps.makeTemporaryDirectory ?? (() => fs33.mkdtemp(path37.join(os16.tmpdir(), "m8t-companion-"))))();
32117
+ const root = await (deps.makeTemporaryDirectory ?? (() => fs38.mkdtemp(path42.join(os17.tmpdir(), "m8t-companion-"))))();
31595
32118
  const dispose = async () => {
31596
- await fs33.rm(root, { recursive: true, force: true }).catch(() => void 0);
32119
+ await fs38.rm(root, { recursive: true, force: true }).catch(() => void 0);
31597
32120
  };
31598
32121
  try {
31599
- const archive = path37.join(root, pinned.asset);
31600
- await fs33.writeFile(archive, bytes, { mode: 384 });
31601
- const unpacked = path37.join(root, "unpacked");
31602
- await fs33.mkdir(unpacked, { recursive: false, mode: 448 });
32122
+ const archive = path42.join(root, pinned.asset);
32123
+ await fs38.writeFile(archive, bytes, { mode: 384 });
32124
+ const unpacked = path42.join(root, "unpacked");
32125
+ await fs38.mkdir(unpacked, { recursive: false, mode: 448 });
31603
32126
  await (deps.extract ?? extractArchive)(archive, unpacked);
31604
- await fs33.rm(archive, { force: true });
32127
+ await fs38.rm(archive, { force: true });
31605
32128
  return {
31606
32129
  version: component.version,
31607
- artifactManifestPath: path37.join(unpacked, "artifact-v1.json"),
32130
+ artifactManifestPath: path42.join(unpacked, "artifact-v1.json"),
31608
32131
  dispose
31609
32132
  };
31610
32133
  } catch (error) {
@@ -31617,7 +32140,7 @@ async function downloadCompanionArtifact(component, deps = {}) {
31617
32140
  function defaultLocalCompanionInstallOptions() {
31618
32141
  const cliEntry = process.argv[1];
31619
32142
  if (!cliEntry) throw new Error("Cannot resolve the installed CLI entry");
31620
- const homeDirectory = os17.homedir();
32143
+ const homeDirectory = os18.homedir();
31621
32144
  const platform = process.platform;
31622
32145
  return {
31623
32146
  homeDirectory,
@@ -31635,7 +32158,7 @@ async function convergeCompanionFromChannel(converge2, options = {}) {
31635
32158
  let artifactManifestPath;
31636
32159
  let dispose = () => Promise.resolve();
31637
32160
  if (stagedDirectory !== void 0) {
31638
- artifactManifestPath = path38.resolve(stagedDirectory, "artifact-v1.json");
32161
+ artifactManifestPath = path43.resolve(stagedDirectory, "artifact-v1.json");
31639
32162
  } else {
31640
32163
  const release = await readCompanionRelease(
31641
32164
  platformVersion !== void 0 ? { channel: true, version: platformTag(platformVersion) } : { url: CHANNEL_LATEST_URL }
@@ -31677,7 +32200,7 @@ Version: ${state.version}
31677
32200
  }
31678
32201
  var CompanionInstallCommand = class extends M8tCommand {
31679
32202
  static paths = [["companion", "install"]];
31680
- static usage = Command55.Usage({
32203
+ static usage = Command57.Usage({
31681
32204
  description: "Install the desktop companions for this user from the release channel.",
31682
32205
  examples: [
31683
32206
  ["Install the released build", "$0 companion install"],
@@ -31687,10 +32210,10 @@ var CompanionInstallCommand = class extends M8tCommand {
31687
32210
  ]
31688
32211
  ]
31689
32212
  });
31690
- from = Option52.String("--from", {
32213
+ from = Option54.String("--from", {
31691
32214
  description: "A locally staged build directory instead of the released one."
31692
32215
  });
31693
- resourceGroup = Option52.String("--resource-group", {
32216
+ resourceGroup = Option54.String("--resource-group", {
31694
32217
  description: "Which deployment to bind to, when the subscription holds more than one."
31695
32218
  });
31696
32219
  async executeCommand() {
@@ -31713,7 +32236,7 @@ function resolveRepoRootMarker(args) {
31713
32236
  }
31714
32237
  async function looksLikeCheckout(dir) {
31715
32238
  try {
31716
- return (await fs34.stat(path39.join(dir, "brain-template"))).isDirectory();
32239
+ return (await fs39.stat(path44.join(dir, "brain-template"))).isDirectory();
31717
32240
  } catch {
31718
32241
  return false;
31719
32242
  }
@@ -31729,21 +32252,21 @@ var defaultDeps2 = {
31729
32252
  convergeCompanion: (platformVersion) => convergeCompanionFromChannel(installCompanion, {
31730
32253
  ...platformVersion !== void 0 ? { platformVersion } : {}
31731
32254
  }),
31732
- homedir: () => os18.homedir()
32255
+ homedir: () => os19.homedir()
31733
32256
  };
31734
32257
  async function finalizeInstall(args, deps = defaultDeps2) {
31735
- const markerDir = path39.join(deps.homedir(), ".m8t");
31736
- const markerPath = path39.join(markerDir, "repo-root");
32258
+ const markerDir = path44.join(deps.homedir(), ".m8t");
32259
+ const markerPath = path44.join(markerDir, "repo-root");
31737
32260
  const cwd = process.cwd();
31738
- const existing = await fs34.readFile(markerPath, "utf8").then((s) => s.trim()).catch(() => null);
32261
+ const existing = await fs39.readFile(markerPath, "utf8").then((s) => s.trim()).catch(() => null);
31739
32262
  const repoRoot = resolveRepoRootMarker({
31740
32263
  ...args.repoRoot !== void 0 ? { explicit: args.repoRoot } : {},
31741
32264
  cwd,
31742
32265
  cwdIsCheckout: await looksLikeCheckout(cwd),
31743
32266
  existing
31744
32267
  });
31745
- await fs34.mkdir(markerDir, { recursive: true });
31746
- await fs34.writeFile(markerPath, `${repoRoot}
32268
+ await fs39.mkdir(markerDir, { recursive: true });
32269
+ await fs39.writeFile(markerPath, `${repoRoot}
31747
32270
  `, "utf8");
31748
32271
  let webappUrl;
31749
32272
  try {
@@ -31821,7 +32344,7 @@ async function finalizeInstall(args, deps = defaultDeps2) {
31821
32344
  }
31822
32345
  let brainOrg = null;
31823
32346
  try {
31824
- const credsRaw = await fs34.readFile(path39.join(markerDir, "github-app.json"), "utf8");
32347
+ const credsRaw = await fs39.readFile(path44.join(markerDir, "github-app.json"), "utf8");
31825
32348
  const creds = JSON.parse(credsRaw);
31826
32349
  brainOrg = typeof creds.org === "string" ? creds.org : null;
31827
32350
  } catch {
@@ -31903,7 +32426,7 @@ var BootstrapStatusCommand = class extends M8tCommand {
31903
32426
  // runbooks and shakedown recipes that a founder may already be part-way
31904
32427
  // through — it prints a deprecation notice and does the right thing.
31905
32428
  static paths = [["bootstrap", "status"], ["bootstrap", "finish"]];
31906
- static usage = Command56.Usage({
32429
+ static usage = Command58.Usage({
31907
32430
  description: "Show the cloud installer's live status (phase, progress, result) \u2014 and finish the local setup when it lands.",
31908
32431
  details: "Reads the durable status blob written by the installer. --watch polls until the install reaches done or failed.\n\nOn reaching done under --watch this also completes the local half of the install, which nothing else in the bootstrap path can do: it registers the webapp's sign-in redirect URI (the installer runs as a managed identity with no directory role, and at launch time the gateway FQDN did not exist yet), writes ~/.m8t/repo-root and the gateway discovery cache, and seeds your advisors' brains from the onboarding intake. Re-runnable \u2014 `m8t bootstrap finish` is a deprecated alias that does exactly this on an already-done install.",
31909
32432
  examples: [
@@ -31912,12 +32435,12 @@ var BootstrapStatusCommand = class extends M8tCommand {
31912
32435
  ["Redo the local setup on a finished install", "$0 bootstrap status --finalize --repo-root /path/to/m8t"]
31913
32436
  ]
31914
32437
  });
31915
- watch = Option53.Boolean("--watch", false);
31916
- output = Option53.String("--output");
31917
- repoRoot = Option53.String("--repo-root", { description: "The m8t clone to point local tools at (default: the current directory)." });
31918
- finalize = Option53.Boolean("--finalize", false, { description: "Complete the local setup against an already-done install, without watching." });
31919
- subscription = Option53.String("--subscription");
31920
- resourceGroup = Option53.String("--resource-group");
32438
+ watch = Option55.Boolean("--watch", false);
32439
+ output = Option55.String("--output");
32440
+ repoRoot = Option55.String("--repo-root", { description: "The m8t clone to point local tools at (default: the current directory)." });
32441
+ finalize = Option55.Boolean("--finalize", false, { description: "Complete the local setup against an already-done install, without watching." });
32442
+ subscription = Option55.String("--subscription");
32443
+ resourceGroup = Option55.String("--resource-group");
31921
32444
  async executeCommand() {
31922
32445
  const state = await readBootstrapState();
31923
32446
  if (!state) {
@@ -32050,7 +32573,7 @@ function formatStatus(d) {
32050
32573
  }
32051
32574
 
32052
32575
  // src/commands/bootstrap/reap.ts
32053
- import { Command as Command57, Option as Option54 } from "clipanion";
32576
+ import { Command as Command59, Option as Option56 } from "clipanion";
32054
32577
  init_errors();
32055
32578
 
32056
32579
  // src/lib/bootstrap-reap.ts
@@ -32144,7 +32667,7 @@ async function reapInstaller(opts) {
32144
32667
  // src/commands/bootstrap/reap.ts
32145
32668
  var BootstrapReapCommand = class extends M8tCommand {
32146
32669
  static paths = [["bootstrap", "reap"]];
32147
- static usage = Command57.Usage({
32670
+ static usage = Command59.Usage({
32148
32671
  description: "Tear down the installer scaffolding (ACI \u2192 MI \u2192 its role assignments) after a successful install.",
32149
32672
  details: "Runs locally on the 'done' signal (the installer can't delete its own identity). The platform RG and the gateway's own assignments persist. A failed install is left intact for diagnosis unless --force.\n\n--sweep-orphans is a DIFFERENT and much broader mode: instead of reaping this install, it scans the WHOLE SUBSCRIPTION for m8t role assignments left behind by installs whose resources are gone \u2014 orphaned installer Owner-at-subscription-scope grants and orphaned gateway subscription-scope roles. It is a dry run that only lists what it found unless you also pass --yes, which deletes them.",
32150
32673
  examples: [
@@ -32154,9 +32677,9 @@ var BootstrapReapCommand = class extends M8tCommand {
32154
32677
  ["\u2026and delete them", "$0 bootstrap reap --sweep-orphans --yes"]
32155
32678
  ]
32156
32679
  });
32157
- force = Option54.Boolean("--force", false, { description: "Reap even if the install failed or never reported a status." });
32158
- sweepOrphans = Option54.Boolean("--sweep-orphans", false, { description: "Subscription-wide: find m8t role assignments orphaned by earlier installs. Lists only, unless --yes." });
32159
- yes = Option54.Boolean("--yes", false, { description: "With --sweep-orphans, actually delete what the sweep found." });
32680
+ force = Option56.Boolean("--force", false, { description: "Reap even if the install failed or never reported a status." });
32681
+ sweepOrphans = Option56.Boolean("--sweep-orphans", false, { description: "Subscription-wide: find m8t role assignments orphaned by earlier installs. Lists only, unless --yes." });
32682
+ yes = Option56.Boolean("--yes", false, { description: "With --sweep-orphans, actually delete what the sweep found." });
32160
32683
  async executeCommand() {
32161
32684
  if (this.sweepOrphans === true) {
32162
32685
  const { subscriptionId: sub } = await getAzAccount();
@@ -32250,18 +32773,18 @@ Found ${String(total)} orphaned assignment(s) (${breakdown}) (dry-run). ${colors
32250
32773
  };
32251
32774
 
32252
32775
  // src/commands/bootstrap/ui.ts
32253
- import * as fs36 from "fs";
32254
- import * as os20 from "os";
32255
- import * as path41 from "path";
32256
- import { Command as Command58, Option as Option55 } from "clipanion";
32776
+ import * as fs41 from "fs";
32777
+ import * as os21 from "os";
32778
+ import * as path46 from "path";
32779
+ import { Command as Command60, Option as Option57 } from "clipanion";
32257
32780
  import { DefaultAzureCredential as DefaultAzureCredential24 } from "@azure/identity";
32258
32781
  init_errors();
32259
32782
 
32260
32783
  // src/lib/bootstrap-ui.ts
32261
- import * as fs35 from "fs";
32784
+ import * as fs40 from "fs";
32262
32785
  import * as net from "net";
32263
- import * as os19 from "os";
32264
- import * as path40 from "path";
32786
+ import * as os20 from "os";
32787
+ import * as path45 from "path";
32265
32788
  import { randomBytes as randomBytes3 } from "crypto";
32266
32789
  import { spawn as spawn8, spawnSync as spawnSync6 } from "child_process";
32267
32790
  init_errors();
@@ -32319,7 +32842,7 @@ async function deployIntakeAgent(args) {
32319
32842
 
32320
32843
  // src/lib/bootstrap-ui.ts
32321
32844
  function sleep3(ms) {
32322
- return new Promise((resolve4) => setTimeout(resolve4, ms));
32845
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
32323
32846
  }
32324
32847
  function isAuthorizationShapedError(error) {
32325
32848
  const seen = /* @__PURE__ */ new Set();
@@ -32459,11 +32982,11 @@ async function ensureFounderFoundryRole(args) {
32459
32982
  });
32460
32983
  }
32461
32984
  function writeWebEnvLocal(args) {
32462
- const envPath = path40.join(args.repoRoot, "apps", "web", ".env.local");
32985
+ const envPath = path45.join(args.repoRoot, "apps", "web", ".env.local");
32463
32986
  let prior = "";
32464
- if (fs35.existsSync(envPath)) {
32465
- prior = fs35.readFileSync(envPath, "utf8");
32466
- fs35.copyFileSync(envPath, envPath + ".bak");
32987
+ if (fs40.existsSync(envPath)) {
32988
+ prior = fs40.readFileSync(envPath, "utf8");
32989
+ fs40.copyFileSync(envPath, envPath + ".bak");
32467
32990
  }
32468
32991
  const priorSecret = readValidInternalSecret(prior);
32469
32992
  const internalSecret = priorSecret ?? (args.randomBytesImpl ?? randomBytes3)(32).toString("base64url");
@@ -32489,9 +33012,9 @@ function writeWebEnvLocal(args) {
32489
33012
  "NEXT_PUBLIC_M8T_ONBOARDING=1",
32490
33013
  ""
32491
33014
  ].join("\n");
32492
- fs35.writeFileSync(envPath, body, { encoding: "utf8", mode: 384 });
33015
+ fs40.writeFileSync(envPath, body, { encoding: "utf8", mode: 384 });
32493
33016
  try {
32494
- fs35.chmodSync(envPath, 384);
33017
+ fs40.chmodSync(envPath, 384);
32495
33018
  } catch {
32496
33019
  }
32497
33020
  return envPath;
@@ -32507,10 +33030,10 @@ function readValidInternalSecret(envText) {
32507
33030
  return isValidInternalSecret(values[0]) ? values[0] : void 0;
32508
33031
  }
32509
33032
  function readWebInternalSecret(repoRoot) {
32510
- const envPath = path40.join(repoRoot, "apps", "web", ".env.local");
33033
+ const envPath = path45.join(repoRoot, "apps", "web", ".env.local");
32511
33034
  let secret;
32512
33035
  try {
32513
- secret = readValidInternalSecret(fs35.readFileSync(envPath, "utf8"));
33036
+ secret = readValidInternalSecret(fs40.readFileSync(envPath, "utf8"));
32514
33037
  } catch {
32515
33038
  secret = void 0;
32516
33039
  }
@@ -32534,14 +33057,14 @@ function assertNodeVersion(versionString = process.version) {
32534
33057
  }
32535
33058
  }
32536
33059
  function runInherit(cmd, cmdArgs, cwd, failCode) {
32537
- return new Promise((resolve4, reject) => {
33060
+ return new Promise((resolve6, reject) => {
32538
33061
  const child = spawn8(cmd, cmdArgs, { cwd, stdio: "inherit", shell: process.platform === "win32" });
32539
33062
  child.on("error", (e) => {
32540
33063
  reject(new LocalCliError({ code: failCode, message: `Failed to start '${cmd}': ${e.message}` }));
32541
33064
  });
32542
33065
  child.on("close", (code) => {
32543
33066
  if (code === 0) {
32544
- resolve4();
33067
+ resolve6();
32545
33068
  } else {
32546
33069
  const opts = {
32547
33070
  code: failCode,
@@ -32561,40 +33084,40 @@ async function installWebDeps(repoRoot) {
32561
33084
  });
32562
33085
  await runInherit("pnpm", ["install"], repoRoot, "BOOTSTRAP_UI_INSTALL_FAILED");
32563
33086
  }
32564
- function onboardingUiPaths(home = os19.homedir()) {
32565
- const dir = path40.join(home, ".m8t");
33087
+ function onboardingUiPaths(home = os20.homedir()) {
33088
+ const dir = path45.join(home, ".m8t");
32566
33089
  return {
32567
- logPath: path40.join(dir, "onboarding-ui.log"),
32568
- pidPath: path40.join(dir, "onboarding-ui.pid")
33090
+ logPath: path45.join(dir, "onboarding-ui.log"),
33091
+ pidPath: path45.join(dir, "onboarding-ui.pid")
32569
33092
  };
32570
33093
  }
32571
- function onboardingRelayPaths(home = os19.homedir()) {
32572
- const dir = path40.join(home, ".m8t");
33094
+ function onboardingRelayPaths(home = os20.homedir()) {
33095
+ const dir = path45.join(home, ".m8t");
32573
33096
  return {
32574
- logPath: path40.join(dir, "onboarding-relay.log"),
32575
- pidPath: path40.join(dir, "onboarding-relay.pid")
33097
+ logPath: path45.join(dir, "onboarding-relay.log"),
33098
+ pidPath: path45.join(dir, "onboarding-relay.pid")
32576
33099
  };
32577
33100
  }
32578
33101
  function isLocalPortOpen(port) {
32579
- return new Promise((resolve4) => {
33102
+ return new Promise((resolve6) => {
32580
33103
  const s = net.createConnection({ host: "127.0.0.1", port });
32581
33104
  s.setTimeout(1e3);
32582
33105
  s.on("connect", () => {
32583
33106
  s.destroy();
32584
- resolve4(true);
33107
+ resolve6(true);
32585
33108
  });
32586
33109
  s.on("error", () => {
32587
- resolve4(false);
33110
+ resolve6(false);
32588
33111
  });
32589
33112
  s.on("timeout", () => {
32590
33113
  s.destroy();
32591
- resolve4(false);
33114
+ resolve6(false);
32592
33115
  });
32593
33116
  });
32594
33117
  }
32595
33118
  function removePidFile(pidPath) {
32596
33119
  try {
32597
- fs35.unlinkSync(pidPath);
33120
+ fs40.unlinkSync(pidPath);
32598
33121
  } catch {
32599
33122
  }
32600
33123
  }
@@ -32607,7 +33130,7 @@ function parseManagedPid(text) {
32607
33130
  function readLiveManagedPid(pidPath) {
32608
33131
  let text;
32609
33132
  try {
32610
- text = fs35.readFileSync(pidPath, "utf8").trim();
33133
+ text = fs40.readFileSync(pidPath, "utf8").trim();
32611
33134
  } catch {
32612
33135
  return null;
32613
33136
  }
@@ -32646,8 +33169,8 @@ async function serveOnboardingUiDetached(args) {
32646
33169
  });
32647
33170
  }
32648
33171
  if (managedPid != null) return { alreadyRunning: true, logPath };
32649
- fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
32650
- const fd = fs35.openSync(logPath, "a");
33172
+ fs40.mkdirSync(path45.dirname(logPath), { recursive: true });
33173
+ const fd = fs40.openSync(logPath, "a");
32651
33174
  const child = spawn8("pnpm", ["--filter", "web", "dev"], {
32652
33175
  cwd: args.repoRoot,
32653
33176
  detached: true,
@@ -32656,7 +33179,7 @@ async function serveOnboardingUiDetached(args) {
32656
33179
  // pnpm resolves to pnpm.cmd on Windows, which needs a shell to launch.
32657
33180
  shell: process.platform === "win32"
32658
33181
  });
32659
- fs35.closeSync(fd);
33182
+ fs40.closeSync(fd);
32660
33183
  if (child.pid == null) {
32661
33184
  throw new LocalCliError({
32662
33185
  code: "BOOTSTRAP_UI_DEV_SPAWN_FAILED",
@@ -32665,7 +33188,7 @@ async function serveOnboardingUiDetached(args) {
32665
33188
  });
32666
33189
  }
32667
33190
  child.unref();
32668
- fs35.writeFileSync(pidPath, String(child.pid), "utf8");
33191
+ fs40.writeFileSync(pidPath, String(child.pid), "utf8");
32669
33192
  const deadline = Date.now() + 45e3;
32670
33193
  const sleep5 = (ms) => new Promise((r) => setTimeout(r, ms));
32671
33194
  while (Date.now() < deadline) {
@@ -32697,8 +33220,8 @@ async function serveOnboardingRelayDetached(args) {
32697
33220
  });
32698
33221
  }
32699
33222
  if (managedPid != null) return { alreadyRunning: true, logPath };
32700
- fs35.mkdirSync(path40.dirname(logPath), { recursive: true });
32701
- const fd = fs35.openSync(logPath, "a");
33223
+ fs40.mkdirSync(path45.dirname(logPath), { recursive: true });
33224
+ const fd = fs40.openSync(logPath, "a");
32702
33225
  const child = spawn8("pnpm", ["--filter", "web", "exec", "tsx", "voice-relay-entry.ts"], {
32703
33226
  cwd: args.repoRoot,
32704
33227
  detached: true,
@@ -32716,7 +33239,7 @@ async function serveOnboardingRelayDetached(args) {
32716
33239
  // pnpm resolves to pnpm.cmd on Windows, which needs a shell to launch.
32717
33240
  shell: process.platform === "win32"
32718
33241
  });
32719
- fs35.closeSync(fd);
33242
+ fs40.closeSync(fd);
32720
33243
  if (child.pid == null) {
32721
33244
  throw new LocalCliError({
32722
33245
  code: "BOOTSTRAP_UI_RELAY_SPAWN_FAILED",
@@ -32725,7 +33248,7 @@ async function serveOnboardingRelayDetached(args) {
32725
33248
  });
32726
33249
  }
32727
33250
  child.unref();
32728
- fs35.writeFileSync(pidPath, String(child.pid), "utf8");
33251
+ fs40.writeFileSync(pidPath, String(child.pid), "utf8");
32729
33252
  const deadline = Date.now() + 45e3;
32730
33253
  const sleep5 = (ms) => new Promise((r) => setTimeout(r, ms));
32731
33254
  while (Date.now() < deadline) {
@@ -32747,7 +33270,7 @@ function autoOpenOnboardingUi(url, open3 = tryOpenUrl) {
32747
33270
  function stopPidFile(pidPath) {
32748
33271
  let pidStr;
32749
33272
  try {
32750
- pidStr = fs35.readFileSync(pidPath, "utf8").trim();
33273
+ pidStr = fs40.readFileSync(pidPath, "utf8").trim();
32751
33274
  } catch {
32752
33275
  return false;
32753
33276
  }
@@ -32764,12 +33287,12 @@ function stopPidFile(pidPath) {
32764
33287
  }
32765
33288
  }
32766
33289
  try {
32767
- fs35.unlinkSync(pidPath);
33290
+ fs40.unlinkSync(pidPath);
32768
33291
  } catch {
32769
33292
  }
32770
33293
  return true;
32771
33294
  }
32772
- function stopOnboardingUi(home = os19.homedir()) {
33295
+ function stopOnboardingUi(home = os20.homedir()) {
32773
33296
  const uiStopped = stopPidFile(onboardingUiPaths(home).pidPath);
32774
33297
  const relayStopped = stopPidFile(onboardingRelayPaths(home).pidPath);
32775
33298
  return uiStopped || relayStopped;
@@ -33058,9 +33581,9 @@ async function resolveSubscriptionInventory(args) {
33058
33581
  const scan2 = scanFn(args.subscriptionId);
33059
33582
  void scan2.catch(() => {
33060
33583
  });
33061
- const timeout = new Promise((resolve4) => {
33584
+ const timeout = new Promise((resolve6) => {
33062
33585
  timer = setTimeout(() => {
33063
- resolve4("timeout");
33586
+ resolve6("timeout");
33064
33587
  }, deadlineMs);
33065
33588
  });
33066
33589
  const raced = await Promise.race([scan2, timeout]);
@@ -33091,7 +33614,7 @@ function renderDeployFailure(error) {
33091
33614
  }
33092
33615
  var BootstrapUiCommand = class extends M8tCommand {
33093
33616
  static paths = [["bootstrap", "ui"]];
33094
- static usage = Command58.Usage({
33617
+ static usage = Command60.Usage({
33095
33618
  description: "Deploy Ezra + start the local onboarding chat UI in the background (returns immediately).",
33096
33619
  details: [
33097
33620
  "Run after `m8t bootstrap launch`, in parallel with `status --watch`. Waits for the cloud",
@@ -33112,16 +33635,16 @@ var BootstrapUiCommand = class extends M8tCommand {
33112
33635
  ["Experimental: start the voice relay (no effect on the text-only intake)", "$0 bootstrap ui --repo-root /path/to/m8t --voice"]
33113
33636
  ]
33114
33637
  });
33115
- repoRoot = Option55.String("--repo-root");
33116
- port = Option55.String("--port", "3000");
33117
- endpoint = Option55.String("--endpoint", {
33638
+ repoRoot = Option57.String("--repo-root");
33639
+ port = Option57.String("--port", "3000");
33640
+ endpoint = Option57.String("--endpoint", {
33118
33641
  description: "Foundry project endpoint to target \u2014 overrides discovery when this install's resource group holds more than one Foundry project."
33119
33642
  });
33120
- prepOnly = Option55.Boolean("--prep-only", false);
33121
- skipInstall = Option55.Boolean("--skip-install", false);
33122
- stop = Option55.Boolean("--stop", false);
33123
- foreground = Option55.Boolean("--foreground", false);
33124
- voice = Option55.Boolean("--voice", false, {
33643
+ prepOnly = Option57.Boolean("--prep-only", false);
33644
+ skipInstall = Option57.Boolean("--skip-install", false);
33645
+ stop = Option57.Boolean("--stop", false);
33646
+ foreground = Option57.Boolean("--foreground", false);
33647
+ voice = Option57.Boolean("--voice", false, {
33125
33648
  description: "Experimental: when serving, starts the voice relay and writes the intake voice env var. The onboarding intake is text-only and is unaffected by this flag \u2014 no voice worker is registered for it."
33126
33649
  });
33127
33650
  async executeCommand() {
@@ -33156,7 +33679,7 @@ var BootstrapUiCommand = class extends M8tCommand {
33156
33679
  this.context.stderr.write(` ${colors.dim(m)}
33157
33680
  `);
33158
33681
  };
33159
- if (fs36.existsSync(path41.join(os20.homedir(), ".m8t", "config.yaml"))) {
33682
+ if (fs41.existsSync(path46.join(os21.homedir(), ".m8t", "config.yaml"))) {
33160
33683
  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."));
33161
33684
  }
33162
33685
  const credential2 = new DefaultAzureCredential24();
@@ -33288,10 +33811,10 @@ var BootstrapUiCommand = class extends M8tCommand {
33288
33811
  };
33289
33812
 
33290
33813
  // src/commands/bootstrap/seed-profile.ts
33291
- import { Command as Command59, Option as Option56 } from "clipanion";
33814
+ import { Command as Command61, Option as Option58 } from "clipanion";
33292
33815
  var BootstrapSeedProfileCommand = class extends M8tCommand {
33293
33816
  static paths = [["bootstrap", "seed-profile"]];
33294
- static usage = Command59.Usage({
33817
+ static usage = Command61.Usage({
33295
33818
  description: "Seed your advisors' brains with the founder + company profile from the onboarding intake.",
33296
33819
  details: "Reads the latest onboarding conversation, renders memory/founder.md + memory/company-profile.md (+ their MEMORY.md index lines), and commits them to both <org>/stacey-brain and <org>/ezra-brain via the GitHub App. Idempotent. --watch polls until the founder finishes the intake.",
33297
33820
  examples: [
@@ -33299,11 +33822,11 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
33299
33822
  ["Wait for the founder to finish", "$0 bootstrap seed-profile --watch"]
33300
33823
  ]
33301
33824
  });
33302
- endpoint = Option56.String("--endpoint", { description: "Override the Foundry endpoint (else read from the install status)." });
33303
- brain = Option56.String("--brain", { description: "Seed only this one brain repo, instead of both <org>/stacey-brain and <org>/ezra-brain." });
33304
- watch = Option56.Boolean("--watch", false, { description: "Poll until the intake completes (or --timeout)." });
33305
- timeout = Option56.String("--timeout", { description: "Watch timeout in minutes (default 20)." });
33306
- githubAppCreds = Option56.String("--github-app-creds");
33825
+ endpoint = Option58.String("--endpoint", { description: "Override the Foundry endpoint (else read from the install status)." });
33826
+ brain = Option58.String("--brain", { description: "Seed only this one brain repo, instead of both <org>/stacey-brain and <org>/ezra-brain." });
33827
+ watch = Option58.Boolean("--watch", false, { description: "Poll until the intake completes (or --timeout)." });
33828
+ timeout = Option58.String("--timeout", { description: "Watch timeout in minutes (default 20)." });
33829
+ githubAppCreds = Option58.String("--github-app-creds");
33307
33830
  async executeCommand() {
33308
33831
  const ctx = await resolveSeedContext({
33309
33832
  endpointOverride: typeof this.endpoint === "string" ? this.endpoint : void 0,
@@ -33363,10 +33886,10 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
33363
33886
  };
33364
33887
 
33365
33888
  // src/commands/telemetry/enroll.ts
33366
- import * as fs37 from "fs";
33367
- import * as os21 from "os";
33368
- import * as path42 from "path";
33369
- import { Command as Command60, Option as Option57 } from "clipanion";
33889
+ import * as fs42 from "fs";
33890
+ import * as os22 from "os";
33891
+ import * as path47 from "path";
33892
+ import { Command as Command62, Option as Option59 } from "clipanion";
33370
33893
  init_errors();
33371
33894
 
33372
33895
  // src/lib/telemetry-enroll.ts
@@ -33448,7 +33971,7 @@ async function resolveKeyVaultName(containerAppResourceId) {
33448
33971
  }
33449
33972
  var TelemetryEnrollCommand = class extends M8tCommand {
33450
33973
  static paths = [["telemetry", "enroll"]];
33451
- static usage = Command60.Usage({
33974
+ static usage = Command62.Usage({
33452
33975
  description: "Enroll this installation for operational telemetry (pre-existing installs).",
33453
33976
  details: "Generates an instance id + ingest key from the m8t telemetry ingest and stores the key in your platform Key Vault, the same place the installer writes it on a fresh install. Your installation is identified only by that random instance id \u2014 no contact, company, or subscription details are sent unless you pass them explicitly. Idempotent: refuses if a key already exists.",
33454
33977
  examples: [
@@ -33456,11 +33979,11 @@ var TelemetryEnrollCommand = class extends M8tCommand {
33456
33979
  ["Enroll and share a support contact", "$0 telemetry enroll --contact-email you@example.com --company 'Acme'"]
33457
33980
  ]
33458
33981
  });
33459
- company = Option57.String("--company", { description: "Share your company name with m8t support. Not sent unless you pass it." });
33460
- contactEmail = Option57.String("--contact-email", { description: "Share a contact email with m8t support. Not sent unless you pass it." });
33461
- subscription = Option57.String("--subscription", { description: "Azure subscription id used to find your deployment. Never sent to m8t." });
33462
- resourceGroup = Option57.String("--resource-group", { description: "Resource group to disambiguate discovery, if you have more than one m8t deployment." });
33463
- force = Option57.Boolean("--force", false, { description: "Enroll even when a key is already stored. Use only when m8t support asks you to." });
33982
+ company = Option59.String("--company", { description: "Share your company name with m8t support. Not sent unless you pass it." });
33983
+ contactEmail = Option59.String("--contact-email", { description: "Share a contact email with m8t support. Not sent unless you pass it." });
33984
+ subscription = Option59.String("--subscription", { description: "Azure subscription id used to find your deployment. Never sent to m8t." });
33985
+ resourceGroup = Option59.String("--resource-group", { description: "Resource group to disambiguate discovery, if you have more than one m8t deployment." });
33986
+ force = Option59.Boolean("--force", false, { description: "Enroll even when a key is already stored. Use only when m8t support asks you to." });
33464
33987
  async executeCommand() {
33465
33988
  const account = await getAzAccount();
33466
33989
  const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
@@ -33493,13 +34016,13 @@ var TelemetryEnrollCommand = class extends M8tCommand {
33493
34016
  ...company ? { company } : {},
33494
34017
  ...contactEmail ? { contactEmail } : {}
33495
34018
  });
33496
- const keyDir = fs37.mkdtempSync(path42.join(os21.tmpdir(), "m8t-ingest-key-"));
33497
- const keyFile = path42.join(keyDir, "key");
34019
+ const keyDir = fs42.mkdtempSync(path47.join(os22.tmpdir(), "m8t-ingest-key-"));
34020
+ const keyFile = path47.join(keyDir, "key");
33498
34021
  try {
33499
- fs37.writeFileSync(keyFile, ingestKey, { mode: 384 });
34022
+ fs42.writeFileSync(keyFile, ingestKey, { mode: 384 });
33500
34023
  await runAz(["keyvault", "secret", "set", "--vault-name", kvName, "--name", INGEST_KEY_SECRET, "--file", keyFile, "--only-show-errors"]);
33501
34024
  } finally {
33502
- fs37.rmSync(keyDir, { recursive: true, force: true });
34025
+ fs42.rmSync(keyDir, { recursive: true, force: true });
33503
34026
  }
33504
34027
  this.context.stdout.write(
33505
34028
  `${colors.success("\u2713")} enrolled (instance ${instanceId}); ingest key stored in Key Vault ${kvName}. The gateway picks it up on its next cycle.
@@ -33510,7 +34033,7 @@ var TelemetryEnrollCommand = class extends M8tCommand {
33510
34033
  };
33511
34034
 
33512
34035
  // src/commands/companion/bridge.ts
33513
- import { Command as Command61, Option as Option58 } from "clipanion";
34036
+ import { Command as Command63, Option as Option60 } from "clipanion";
33514
34037
 
33515
34038
  // ../../packages/companion-bridge-contract/src/index.ts
33516
34039
  var COMPANION_MESSAGE_MAX_CODE_POINTS = 32768;
@@ -34628,14 +35151,14 @@ async function runCompanionBridge(stdin, stdout, stderr, deps = defaultDeps3) {
34628
35151
  return 3;
34629
35152
  }
34630
35153
  }
34631
- var CompanionBridgeCommand = class extends Command61 {
35154
+ var CompanionBridgeCommand = class extends Command63 {
34632
35155
  static paths = [["companion", "_bridge"]];
34633
35156
  /**
34634
35157
  * One process serving many requests instead of one per request, so the
34635
35158
  * session keeps its authenticated context between them. A CLI predating the
34636
35159
  * flag rejects it outright, which is how the app knows to fall back.
34637
35160
  */
34638
- serve = Option58.Boolean("--serve", false);
35161
+ serve = Option60.Boolean("--serve", false);
34639
35162
  async execute() {
34640
35163
  if (this.serve) {
34641
35164
  return runCompanionBridgeServe(
@@ -34653,7 +35176,7 @@ var CompanionBridgeCommand = class extends Command61 {
34653
35176
  };
34654
35177
 
34655
35178
  // src/commands/companion/status.ts
34656
- import { Command as Command62 } from "clipanion";
35179
+ import { Command as Command64 } from "clipanion";
34657
35180
  async function withTimeout(work, ms) {
34658
35181
  let timer;
34659
35182
  try {
@@ -34725,7 +35248,7 @@ Run: m8t companion install
34725
35248
  }
34726
35249
  var CompanionStatusCommand = class extends M8tCommand {
34727
35250
  static paths = [["companion", "status"]];
34728
- static usage = Command62.Usage({
35251
+ static usage = Command64.Usage({
34729
35252
  description: "Verify the installed desktop companion without launching it."
34730
35253
  });
34731
35254
  async executeCommand() {
@@ -34739,7 +35262,7 @@ var CompanionStatusCommand = class extends M8tCommand {
34739
35262
  };
34740
35263
 
34741
35264
  // src/commands/companion/repair.ts
34742
- import { Command as Command63, Option as Option59 } from "clipanion";
35265
+ import { Command as Command65, Option as Option61 } from "clipanion";
34743
35266
  async function runCompanionRepairCommand(stdout, repair) {
34744
35267
  const state = await repair();
34745
35268
  if (state.state === "not-released") {
@@ -34758,10 +35281,10 @@ async function runCompanionRepairCommand(stdout, repair) {
34758
35281
  }
34759
35282
  var CompanionRepairCommand = class extends M8tCommand {
34760
35283
  static paths = [["companion", "repair"]];
34761
- static usage = Command63.Usage({
35284
+ static usage = Command65.Usage({
34762
35285
  description: "Restore the desktop companions and start-at-login state."
34763
35286
  });
34764
- resourceGroup = Option59.String("--resource-group", {
35287
+ resourceGroup = Option61.String("--resource-group", {
34765
35288
  description: "Which deployment to bind to, when the subscription holds more than one."
34766
35289
  });
34767
35290
  async executeCommand() {
@@ -34775,7 +35298,7 @@ var CompanionRepairCommand = class extends M8tCommand {
34775
35298
  };
34776
35299
 
34777
35300
  // src/commands/companion/uninstall.ts
34778
- import { Command as Command64 } from "clipanion";
35301
+ import { Command as Command66 } from "clipanion";
34779
35302
  async function runCompanionUninstallCommand(stdout, uninstall) {
34780
35303
  const state = await uninstall();
34781
35304
  if (state.state !== "not-installed") {
@@ -34787,7 +35310,7 @@ async function runCompanionUninstallCommand(stdout, uninstall) {
34787
35310
  }
34788
35311
  var CompanionUninstallCommand = class extends M8tCommand {
34789
35312
  static paths = [["companion", "uninstall"]];
34790
- static usage = Command64.Usage({
35313
+ static usage = Command66.Usage({
34791
35314
  description: "Remove only this user's desktop companion installation."
34792
35315
  });
34793
35316
  async executeCommand() {
@@ -34836,6 +35359,8 @@ cli.register(BrainOrgsCommand);
34836
35359
  cli.register(BrainShowCommand);
34837
35360
  cli.register(BrainUnlinkCommand);
34838
35361
  cli.register(ArchitectCheckCommand);
35362
+ cli.register(AgentContentSyncCommand);
35363
+ cli.register(AgentContentPinCommand);
34839
35364
  cli.register(CoderDeployCommand);
34840
35365
  cli.register(CoderTeardownCommand);
34841
35366
  cli.register(AzureExecDeployCommand);