run402 4.16.0 → 4.17.0

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.
@@ -0,0 +1,217 @@
1
+ import assert from "node:assert/strict";
2
+ import { chmodSync, mkdtempSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { describe, it } from "node:test";
6
+ import { bech32 } from "@scure/base";
7
+ import {
8
+ buildBuzzDoctorReport,
9
+ BUZZ_DOCTOR_REPAIR_MATRIX,
10
+ isPublicAddress,
11
+ normalizeNostrSubject,
12
+ parseBuzzDoctorArgs,
13
+ pinnedLookup,
14
+ } from "./buzz-doctor.mjs";
15
+ import { BUZZ_DOCTOR_CHECK_ORDER, BUZZ_DOCTOR_CONTRACT, validateBuzzDoctorReport } from "./buzz-doctor-contract.mjs";
16
+
17
+ const SUBJECT = "6b6951a5738dfe576d0c44bf7a5f8afe655005a156f9d3e648d81437c3f5ebbf";
18
+ const OTHER_SUBJECT = "a".repeat(64);
19
+
20
+ function makeBuzzBin() {
21
+ const directory = mkdtempSync(join(tmpdir(), "run402-buzz-doctor-"));
22
+ const executable = join(directory, "buzz");
23
+ writeFileSync(executable, "#!/bin/sh\nexit 0\n");
24
+ chmodSync(executable, 0o755);
25
+ return { directory, executable };
26
+ }
27
+
28
+ function commandOk(stdout = "") {
29
+ return { status: 0, stdout, stderr: "" };
30
+ }
31
+
32
+ function commandError(code = "ENOENT") {
33
+ return { status: null, stdout: "", stderr: "", error: Object.assign(new Error(code), { code }) };
34
+ }
35
+
36
+ function helpFor(args) {
37
+ const key = args.join(" ");
38
+ if (key === "--help") return "Buzz CLI — interact with a Buzz relay\nusers\nsocial\nErrors are JSON on stderr";
39
+ if (key === "users get --help") return "Usage: buzz users get\n--pubkey\nOmit for your own profile";
40
+ if (key === "social publish --help") return "Usage: buzz social publish\n--content";
41
+ if (key === "social event --help") return "Usage: buzz social event\n--event";
42
+ return null;
43
+ }
44
+
45
+ function healthyDependencies(overrides = {}) {
46
+ const { directory, executable } = makeBuzzBin();
47
+ const calls = [];
48
+ const env = {
49
+ SHELL: "/bin/sh",
50
+ PATH: directory,
51
+ BUZZ_RELAY_URL: "wss://community.example",
52
+ RUN402_ACTIVE_WALLET_JSON: JSON.stringify({ name: "buzz-fizz", source: "flag", sourceDetail: "--wallet" }),
53
+ };
54
+ const runCommand = (command, args) => {
55
+ calls.push([command, ...args]);
56
+ if (command === "/bin/sh") return commandOk();
57
+ if (command === "/opt/node") return commandOk("v22.12.0\n");
58
+ if (command === executable || command.endsWith("/buzz")) {
59
+ const help = helpFor(args);
60
+ if (help !== null) return commandOk(help);
61
+ if (args.join(" ") === "users get") return commandOk(JSON.stringify([{ pubkey: SUBJECT, display_name: "Fizz" }]));
62
+ }
63
+ return commandError();
64
+ };
65
+ return {
66
+ expectedSubjectHex: SUBJECT,
67
+ env,
68
+ execPath: "/opt/node",
69
+ cliExecutable: "/opt/run402",
70
+ cwd: "/tmp",
71
+ runCommand,
72
+ lookup: async () => [{ address: "93.184.216.34", family: 4 }],
73
+ pinnedRelayRead: async () => ({ ok: true, status: 200, elapsed_ms: 4 }),
74
+ originProbe: async () => ({ ok: true, status: 200, elapsed_ms: 3 }),
75
+ updateCheck: async () => ({ name: "cli_update", status: "ok" }),
76
+ getActiveProfile: () => "buzz-fizz",
77
+ profileExistsImpl: () => true,
78
+ readMetaImpl: () => ({ name: "buzz-fizz", rail: "x402" }),
79
+ apiOrigin: "https://api.run402.com",
80
+ consoleOrigin: "https://console.run402.com",
81
+ now: Date.parse("2026-07-31T12:00:00.000Z"),
82
+ calls,
83
+ ...overrides,
84
+ };
85
+ }
86
+
87
+ describe("Buzz doctor argument and identity contract", () => {
88
+ it("accepts an explicit hex or npub target and rejects malformed/repeated combinations before probing", () => {
89
+ const npub = bech32.encode("npub", bech32.toWords(Buffer.from(SUBJECT, "hex")));
90
+ assert.deepEqual(parseBuzzDoctorArgs(["--buzz", "--buzz-agent", SUBJECT]), { buzz: true, expectedSubjectHex: SUBJECT });
91
+ assert.deepEqual(parseBuzzDoctorArgs(["--buzz", "--buzz-agent", npub]), { buzz: true, expectedSubjectHex: SUBJECT });
92
+ assert.equal(parseBuzzDoctorArgs(["--buzz-agent", SUBJECT]).error.code, "BUZZ_MODE_REQUIRED");
93
+ assert.equal(parseBuzzDoctorArgs(["--buzz", "--buzz-agent"]).error.code, "BAD_FLAG");
94
+ assert.equal(parseBuzzDoctorArgs(["--buzz", "--buzz-agent", "not-an-npub"]).error.code, "BAD_BUZZ_AGENT");
95
+ assert.equal(parseBuzzDoctorArgs(["--buzz", "--buzz-agent", SUBJECT, "--buzz-agent", SUBJECT]).error.code, "DUPLICATE_FLAG");
96
+ assert.equal(normalizeNostrSubject(npub), SUBJECT);
97
+ });
98
+ });
99
+
100
+ describe("Buzz doctor bounded zero-mutation runner", () => {
101
+ it("returns the frozen ordered passing report without invoking a Buzz write or unrelated Run402 check", async () => {
102
+ const dependencies = healthyDependencies();
103
+ const report = await buildBuzzDoctorReport(dependencies);
104
+ assert.equal(report.ok, true);
105
+ assert.equal(report.mode, "buzz");
106
+ assert.equal(report.mutation_state, "not_started");
107
+ assert.deepEqual(report.checks.map((check) => check.name), BUZZ_DOCTOR_CHECK_ORDER);
108
+ assert.ok(report.checks.every((check) => check.status === "ok"));
109
+ assert.equal(report.checks.find((check) => check.name === "buzz_cli").value.version_status, "version_unknown_capabilities_ok");
110
+ assert.equal(report.checks.find((check) => check.name === "buzz_agent_target").value.observed_subject_hex, SUBJECT);
111
+ assert.equal(dependencies.calls.some((call) => call.includes("publish")), true, "publish help capability is expected");
112
+ assert.equal(dependencies.calls.some((call) => call.join(" ").includes("publish --content")), false, "doctor must never publish");
113
+ assert.equal(dependencies.calls.some((call) => call.includes("--version") && call[0].endsWith("buzz")), false, "released Buzz has no version flag");
114
+ const validation = validateBuzzDoctorReport(report, {
115
+ expectedSubjectHex: SUBJECT,
116
+ walletProfile: "buzz-fizz",
117
+ nodeExecutable: "/opt/node",
118
+ run402Executable: "/opt/run402",
119
+ relayOrigin: "wss://community.example",
120
+ now: dependencies.now,
121
+ });
122
+ assert.deepEqual(validation, { valid: true, reason: null });
123
+ });
124
+
125
+ it("continues through independent shell, Node, client, origin, relay, target, and profile failures", async () => {
126
+ const dependencies = healthyDependencies();
127
+ dependencies.env.SHELL = "";
128
+ dependencies.execPath = "/missing/node";
129
+ dependencies.runCommand = (command, args) => {
130
+ if (command === "/missing/node") return commandError();
131
+ if (command.endsWith("/buzz")) {
132
+ if (args.join(" ") === "--help") return commandOk("incompatible help");
133
+ return commandError();
134
+ }
135
+ return commandError();
136
+ };
137
+ dependencies.originProbe = async () => ({ ok: false, status: 503, failure: "http_503" });
138
+ dependencies.lookup = async () => [
139
+ { address: "93.184.216.34", family: 4 },
140
+ { address: "127.0.0.1", family: 4 },
141
+ ];
142
+ dependencies.profileExistsImpl = () => false;
143
+ const report = await buildBuzzDoctorReport(dependencies);
144
+ assert.equal(report.ok, false);
145
+ const blocked = Object.fromEntries(report.checks.filter((check) => check.status === "blocked").map((check) => [check.name, check]));
146
+ assert.equal(blocked.session_shell.code, "BUZZ_PREFLIGHT_SHELL_UNAVAILABLE");
147
+ assert.equal(blocked.node_runtime.code, "BUZZ_PREFLIGHT_NODE_UNAVAILABLE");
148
+ assert.equal(blocked.buzz_cli.code, "BUZZ_PREFLIGHT_BUZZ_CLI_INCOMPATIBLE");
149
+ assert.equal(blocked.buzz_agent_target.code, "BUZZ_AGENT_TARGET_UNVERIFIED");
150
+ assert.equal(blocked.run402_api.code, "BUZZ_PREFLIGHT_API_UNREACHABLE");
151
+ assert.equal(blocked.run402_console.code, "BUZZ_PREFLIGHT_CONSOLE_UNREACHABLE");
152
+ assert.equal(blocked.buzz_relay.code, "BUZZ_PREFLIGHT_RELAY_UNSAFE");
153
+ assert.equal(blocked.wallet_profile.code, "BUZZ_PREFLIGHT_WALLET_PROFILE_NOT_FOUND");
154
+ for (const check of Object.values(blocked)) assert.equal(check.next_actions.length, 1, check.name);
155
+ assert.equal(blocked.buzz_cli.next_actions[0].surface, "buzz_settings");
156
+ assert.equal("argv" in blocked.buzz_cli.next_actions[0], false);
157
+ assert.deepEqual(blocked.wallet_profile.next_actions[0].argv, ["run402", "wallets", "new", "buzz-fizz"]);
158
+ });
159
+
160
+ it("fails closed when the released public self profile is absent or belongs to another agent", async () => {
161
+ const absent = healthyDependencies();
162
+ const originalAbsentRunner = absent.runCommand;
163
+ absent.runCommand = (command, args, options) => args.join(" ") === "users get"
164
+ ? commandOk("[]")
165
+ : originalAbsentRunner(command, args, options);
166
+ let report = await buildBuzzDoctorReport(absent);
167
+ assert.equal(report.checks.find((check) => check.name === "buzz_agent_target").code, "BUZZ_AGENT_TARGET_UNVERIFIED");
168
+
169
+ const mismatch = healthyDependencies();
170
+ const originalMismatchRunner = mismatch.runCommand;
171
+ mismatch.runCommand = (command, args, options) => args.join(" ") === "users get"
172
+ ? commandOk(JSON.stringify([{ pubkey: OTHER_SUBJECT }]))
173
+ : originalMismatchRunner(command, args, options);
174
+ report = await buildBuzzDoctorReport(mismatch);
175
+ const target = report.checks.find((check) => check.name === "buzz_agent_target");
176
+ assert.equal(target.code, "BUZZ_AGENT_TARGET_MISMATCH");
177
+ assert.equal(target.value.expected_subject_hex, SUBJECT);
178
+ assert.equal(target.value.observed_subject_hex, OTHER_SUBJECT);
179
+ });
180
+
181
+ it("treats compatible stale Run402 as warning and preserves executable argv guidance", async () => {
182
+ const dependencies = healthyDependencies({
183
+ updateCheck: async () => ({
184
+ name: "cli_update",
185
+ status: "warning",
186
+ value: { next_actions: [{ argv: ["npm", "install", "-g", "run402@latest"], cwd: "/tmp" }] },
187
+ }),
188
+ });
189
+ const report = await buildBuzzDoctorReport(dependencies);
190
+ const check = report.checks.find((entry) => entry.name === "run402_cli");
191
+ assert.equal(check.status, "warning");
192
+ assert.equal(check.code, "BUZZ_PREFLIGHT_RUN402_UPDATE_AVAILABLE");
193
+ assert.deepEqual(check.next_actions[0].argv, ["npm", "install", "-g", "run402@latest"]);
194
+ assert.equal(report.ok, true);
195
+ });
196
+
197
+ it("rejects private, loopback, link-local, mapped, and documentation addresses", () => {
198
+ for (const address of ["127.0.0.1", "10.0.0.1", "169.254.169.254", "192.0.2.1", "::1", "fc00::1", "fe80::1", "::ffff:127.0.0.1", "2001:db8::1"]) {
199
+ assert.equal(isPublicAddress(address), false, address);
200
+ }
201
+ assert.equal(isPublicAddress("93.184.216.34"), true);
202
+ assert.equal(isPublicAddress("2606:4700:4700::1111"), true);
203
+ });
204
+
205
+ it("pins relay connections to the validated address and exhaustively maps every stable code", () => {
206
+ const callbackResults = [];
207
+ const lookup = pinnedLookup({ address: "93.184.216.34", family: 4 }, "community.example");
208
+ lookup("community.example", {}, (error, address, family) => callbackResults.push({ error, address, family }));
209
+ lookup("changed.example", {}, (error, address, family) => callbackResults.push({ error, address, family }));
210
+ assert.deepEqual(callbackResults[0], { error: null, address: "93.184.216.34", family: 4 });
211
+ assert.equal(callbackResults[1].error.message, "relay_hostname_changed");
212
+ assert.equal(callbackResults[1].address, undefined);
213
+
214
+ const contractCodes = Object.values(BUZZ_DOCTOR_CONTRACT.codes_by_check).flat().sort();
215
+ assert.deepEqual(Object.keys(BUZZ_DOCTOR_REPAIR_MATRIX).sort(), contractCodes);
216
+ });
217
+ });
package/lib/buzz.mjs CHANGED
@@ -21,11 +21,13 @@ The four independent states are:
21
21
 
22
22
  Canonical workflows:
23
23
  run402 buzz status
24
- run402 buzz adopt --org <org_id> --identity-link <idlnk_id>
24
+ run402 buzz adopt offer --org <org_id> --identity-link <idlnk_id> [--deployment-context-file <json>]
25
25
  run402 buzz install --org <org_id> --community <buzz:community:host> --authority <hex-pubkey>
26
26
  run402 buzz enroll --installation <buzzci_id> --identity-link <idlnk_id> --grants-file <json> --expires-at <ISO-8601>
27
27
 
28
28
  Explicit consent/decision commands:
29
+ run402 buzz adopt offer show <buzzhao_id>
30
+ run402 buzz adopt offer cancel <buzzhao_id>
29
31
  run402 buzz adopt complete <buzzha_id> --event-file <owner-event.json>
30
32
  run402 buzz adopt cancel <buzzha_id>
31
33
  run402 buzz install activate <buzzci_id> --proof-file <authority-proof.json>
@@ -36,6 +38,7 @@ Explicit consent/decision commands:
36
38
  run402 buzz revoke <buzzae_id>
37
39
 
38
40
  Advanced recovery reads:
41
+ run402 buzz adopt direct --org <org_id> --identity-link <idlnk_id>
39
42
  run402 buzz adopt list --org <org_id>
40
43
  run402 buzz adopt show <buzzha_id>
41
44
  run402 buzz install list --org <org_id>
@@ -93,6 +96,7 @@ async function status(args) {
93
96
 
94
97
  async function adopt(args) {
95
98
  const [operation, ...rest] = args;
99
+ if (operation === "offer") return adoptionOffer(rest);
96
100
  if (operation === "complete") {
97
101
  const values = ["--event-file", "--idempotency-key"];
98
102
  const a = normalizeArgv(rest);
@@ -121,10 +125,11 @@ async function adopt(args) {
121
125
  return invoke(() => getSdk().buzz.humanAdoptions.get(id));
122
126
  }
123
127
 
124
- const a = normalizeArgv(args);
128
+ const directArgs = operation === "direct" ? rest : args;
129
+ const a = normalizeArgv(directArgs);
125
130
  const values = ["--org", "--identity-link", "--idempotency-key"];
126
131
  assertKnownFlags(a, values, values);
127
- requirePositionalCount(a, values, { min: 0, max: 0, command: "run402 buzz adopt --org <org_id> --identity-link <idlnk_id>" });
132
+ requirePositionalCount(a, values, { min: 0, max: 0, command: "run402 buzz adopt direct --org <org_id> --identity-link <idlnk_id>" });
128
133
  return invoke(() => getSdk({ authMode: "wallet" }).buzz.adopt({
129
134
  organizationId: requiredFlag(a, "--org"),
130
135
  identityLinkId: requiredFlag(a, "--identity-link"),
@@ -132,6 +137,46 @@ async function adopt(args) {
132
137
  }));
133
138
  }
134
139
 
140
+ async function adoptionOffer(args) {
141
+ const [operation, ...rest] = args;
142
+ if (operation === "show") {
143
+ const a = normalizeArgv(rest);
144
+ assertKnownFlags(a);
145
+ const [id] = requirePositionalCount(a, [], { min: 1, max: 1, command: "run402 buzz adopt offer show <buzzhao_id>" });
146
+ return invoke(() => getSdk({ authMode: "wallet" }).buzz.humanAdoptionOffers.get(id));
147
+ }
148
+ if (operation === "cancel") {
149
+ const a = normalizeArgv(rest);
150
+ const values = ["--idempotency-key"];
151
+ assertKnownFlags(a, values, values);
152
+ const [id] = requirePositionalCount(a, values, { min: 1, max: 1, command: "run402 buzz adopt offer cancel <buzzhao_id>" });
153
+ return invoke(() => getSdk({ authMode: "wallet" }).buzz.humanAdoptionOffers.cancel(id, flagValue(a, "--idempotency-key") ?? undefined));
154
+ }
155
+ const a = normalizeArgv(args);
156
+ const values = ["--org", "--identity-link", "--deployment-context-file", "--idempotency-key"];
157
+ assertKnownFlags(a, values, values);
158
+ requirePositionalCount(a, values, { min: 0, max: 0, command: "run402 buzz adopt offer --org <org_id> --identity-link <idlnk_id>" });
159
+ const deploymentPath = flagValue(a, "--deployment-context-file");
160
+ return invoke(async () => {
161
+ const client = getSdk({ authMode: "wallet" });
162
+ const status = await client.buzz.status();
163
+ if (!status.buzz?.capabilities?.human_adoption_offers) {
164
+ fail({
165
+ code: "BUZZ_ADOPTION_OFFERS_UNSUPPORTED",
166
+ message: "The selected Run402 gateway does not support conversational human-adoption offers; no mutation was attempted.",
167
+ hint: "Upgrade the run402 client/gateway. The advanced compatibility flow remains available as `run402 buzz adopt direct --org <org_id> --identity-link <idlnk_id>`.",
168
+ safe_to_retry: true,
169
+ });
170
+ }
171
+ return client.buzz.offerAdoption({
172
+ organizationId: requiredFlag(a, "--org"),
173
+ identityLinkId: requiredFlag(a, "--identity-link"),
174
+ deploymentContext: deploymentPath ? readJsonFile(deploymentPath, "--deployment-context-file") : undefined,
175
+ idempotencyKey: flagValue(a, "--idempotency-key") ?? undefined,
176
+ });
177
+ });
178
+ }
179
+
135
180
  async function install(args) {
136
181
  const [operation, ...rest] = args;
137
182
  if (operation === "activate") {
package/lib/buzz.test.mjs CHANGED
@@ -57,6 +57,69 @@ describe("run402 buzz CLI", () => {
57
57
  assert.match(stderr.join("\n"), /predates/);
58
58
  });
59
59
 
60
+ it("creates the canonical conversational adoption offer after capability detection", async () => {
61
+ const directory = mkdtempSync(join(tmpdir(), "run402-buzz-offer-cli-"));
62
+ const contextPath = join(directory, "deployment.json");
63
+ const deploymentContext = {
64
+ project_id: "prj_church",
65
+ release_id: "rel_demo",
66
+ live_url: "https://church.run402.com/",
67
+ source_revision: "abc123",
68
+ verified_at: "2026-07-31T10:00:00.000Z",
69
+ };
70
+ writeFileSync(contextPath, JSON.stringify(deploymentContext));
71
+ let observed;
72
+ sdk = {
73
+ buzz: {
74
+ status: async () => ({
75
+ supported: true,
76
+ buzz: { capabilities: { human_adoption_offers: true, browser_fragment_v1: true } },
77
+ }),
78
+ offerAdoption: async (input) => {
79
+ observed = input;
80
+ return {
81
+ buzz_human_adoption_offer_id: `buzzhao_${"1".repeat(32)}`,
82
+ status: "available",
83
+ handoff_url: `https://console.run402.com/buzz/adoptions/buzzhao_${"1".repeat(32)}`,
84
+ };
85
+ },
86
+ },
87
+ };
88
+ try {
89
+ await run("adopt", [
90
+ "offer",
91
+ "--org", `org_${"2".repeat(32)}`,
92
+ "--identity-link", `idlnk_${"3".repeat(32)}`,
93
+ "--deployment-context-file", contextPath,
94
+ "--idempotency-key", "offer-after-demo-1",
95
+ ]);
96
+ } finally {
97
+ rmSync(directory, { recursive: true, force: true });
98
+ }
99
+ assert.deepEqual(observed.deploymentContext, deploymentContext);
100
+ assert.equal(observed.idempotencyKey, "offer-after-demo-1");
101
+ assert.deepEqual(authModes, ["wallet"]);
102
+ assert.equal(JSON.parse(stdout[0]).status, "available");
103
+ assert.doesNotMatch(stdout[0], /private|session|credential/i);
104
+ });
105
+
106
+ it("polls and cancels offers with the initiating agent wallet", async () => {
107
+ const calls = [];
108
+ sdk = {
109
+ buzz: {
110
+ humanAdoptionOffers: {
111
+ get: async (id) => { calls.push(["get", id]); return { status: "available" }; },
112
+ cancel: async (id, key) => { calls.push(["cancel", id, key]); return { status: "cancelled" }; },
113
+ },
114
+ },
115
+ };
116
+ const id = `buzzhao_${"1".repeat(32)}`;
117
+ await run("adopt", ["offer", "show", id]);
118
+ await run("adopt", ["offer", "cancel", id, "--idempotency-key", "cancel-1"]);
119
+ assert.deepEqual(calls, [["get", id], ["cancel", id, "cancel-1"]]);
120
+ assert.deepEqual(authModes, ["wallet", "wallet"]);
121
+ });
122
+
60
123
  it("maps a Honey enrollment file to the goal-shaped SDK call and prints only JSON", async () => {
61
124
  const directory = mkdtempSync(join(tmpdir(), "run402-buzz-cli-"));
62
125
  const grantsPath = join(directory, "grants.json");
@@ -50,7 +50,8 @@ export const COMMAND_MANIFEST = [
50
50
 
51
51
  // ── Buzz community ↔ Run402 control plane ───────────────────────────────
52
52
  { path: ["buzz", "status"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: [], skipBehavioral: "requires live principal authentication" },
53
- { path: ["buzz", "adopt"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--org", "org_11111111111111111111111111111111", "--identity-link", "idlnk_11111111111111111111111111111111"], skipBehavioral: "requires eligible sole agent owner and live Buzz identity" },
53
+ { path: ["buzz", "adopt", "offer"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--org", "org_11111111111111111111111111111111", "--identity-link", "idlnk_11111111111111111111111111111111"], skipBehavioral: "requires eligible sole agent owner, live Buzz identity, and offer-capable gateway" },
54
+ { path: ["buzz", "adopt", "direct"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--org", "org_11111111111111111111111111111111", "--identity-link", "idlnk_11111111111111111111111111111111"], skipBehavioral: "advanced compatibility flow requiring eligible sole agent owner and live Buzz identity" },
54
55
  { path: ["buzz", "install"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--org", "org_11111111111111111111111111111111", "--community", "buzz:community:relay.example", "--authority", "11".repeat(32)], skipBehavioral: "requires owner step-up and a compatible live Buzz relay" },
55
56
  { path: ["buzz", "enroll"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--installation", "buzzci_11111111111111111111111111111111", "--identity-link", "idlnk_11111111111111111111111111111111", "--grants-file", "__FIXTURE_FILE__", "--expires-at", "2026-08-01T00:00:00.000Z"], skipBehavioral: "requires live relay membership evidence and a grant fixture" },
56
57
  { path: ["buzz", "approve"], positionals: [p("buzz_agent_enrollment_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["buzzae_11111111111111111111111111111111", "--grants-file", "__FIXTURE_FILE__", "--descriptor-revision", "1", "--policy-revision", "1"], skipBehavioral: "requires owner step-up and a live pending enrollment" },
@@ -0,0 +1,4 @@
1
+ import { flushDiagnosticTelemetryQueue } from "./diagnostic-telemetry.mjs";
2
+
3
+ const [, , path, apiOrigin] = process.argv;
4
+ await flushDiagnosticTelemetryQueue({ path, apiOrigin });