@toon-protocol/rig 5.3.0 → 5.4.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.
@@ -4,6 +4,7 @@ import {
4
4
  CI_SERVICE_REQUEST_KIND,
5
5
  CI_SERVICE_STOP_KIND,
6
6
  CI_STATUS_USAGE,
7
+ CI_TRUST_ORDER,
7
8
  CI_WORKFLOW_PROGRESS_KIND,
8
9
  CI_WORKFLOW_RESULT_KIND,
9
10
  GitRepoReader,
@@ -27,11 +28,13 @@ import {
27
28
  earliestUniqueCommit,
28
29
  emitCliError,
29
30
  encryptSecretUpdate,
31
+ evaluateCiGate,
30
32
  executePush,
31
33
  generateSecretsKey,
32
34
  getGitRemoteUrls,
33
35
  hexToNpub,
34
36
  initGitRepository,
37
+ isCiTrustLevel,
35
38
  isRelayUrl,
36
39
  isSafeRefname,
37
40
  listGitRemotes,
@@ -58,13 +61,13 @@ import {
58
61
  updateRef,
59
62
  writeGitObjects,
60
63
  writeToonConfig
61
- } from "./chunk-DGF7WCRW.js";
64
+ } from "./chunk-MIK7SRWE.js";
62
65
  import {
63
66
  PREFERRED_GATEWAY,
64
67
  mirrorGatewaysFor,
65
68
  readGateways,
66
69
  shaResolverFor
67
- } from "./chunk-UXRWMKXV.js";
70
+ } from "./chunk-QSUO7J4H.js";
68
71
  import {
69
72
  COMMENT_KIND,
70
73
  DEFAULT_KEYSTORE_PASSWORD,
@@ -93,7 +96,7 @@ import {
93
96
  resolveIdentity,
94
97
  revisionRootId,
95
98
  selectRevision
96
- } from "./chunk-OVZJ5P6E.js";
99
+ } from "./chunk-3KS6S4S5.js";
97
100
  import {
98
101
  ChannelMapStore,
99
102
  channelStatus,
@@ -322,7 +325,7 @@ function loadPaidSession(deps, relayUrl) {
322
325
  });
323
326
  }
324
327
  var defaultLoadStandalone = async (options) => {
325
- const mod = await import("./standalone-mode-E7TNMWGO.js");
328
+ const mod = await import("./standalone-mode-LUWNCDPL.js");
326
329
  return mod.createStandaloneContext(options);
327
330
  };
328
331
  function identityReport(ctx) {
@@ -2520,7 +2523,7 @@ async function runCi(args, deps) {
2520
2523
  case "status":
2521
2524
  return runCiStatus(rest, deps);
2522
2525
  case "serve":
2523
- return (await import("./ci-serve-R7ZQ7GJQ.js")).runCiServe(rest, deps);
2526
+ return (await import("./ci-serve-4RJCKEPV.js")).runCiServe(rest, deps);
2524
2527
  case "--help":
2525
2528
  case "-h":
2526
2529
  case "help":
@@ -2796,7 +2799,7 @@ import {
2796
2799
  PATCH_KIND as PATCH_KIND3,
2797
2800
  REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND3,
2798
2801
  STATUS_APPLIED_KIND as STATUS_APPLIED_KIND3,
2799
- STATUS_CLOSED_KIND as STATUS_CLOSED_KIND2,
2802
+ STATUS_CLOSED_KIND as STATUS_CLOSED_KIND3,
2800
2803
  STATUS_DRAFT_KIND as STATUS_DRAFT_KIND2,
2801
2804
  STATUS_OPEN_KIND as STATUS_OPEN_KIND2
2802
2805
  } from "@toon-protocol/core/nip34";
@@ -2811,7 +2814,8 @@ import { promisify } from "util";
2811
2814
  import {
2812
2815
  PATCH_KIND as PATCH_KIND2,
2813
2816
  REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND2,
2814
- STATUS_APPLIED_KIND as STATUS_APPLIED_KIND2
2817
+ STATUS_APPLIED_KIND as STATUS_APPLIED_KIND2,
2818
+ STATUS_CLOSED_KIND as STATUS_CLOSED_KIND2
2815
2819
  } from "@toon-protocol/core/nip34";
2816
2820
 
2817
2821
  // src/cli/fetch.ts
@@ -3649,6 +3653,12 @@ reported as a partial success; retry with \`rig pr status <patch-id> applied\`.
3649
3653
  Options:
3650
3654
  --target <branch> branch to merge onto (default: the patch's branch-name
3651
3655
  tag, else the repo's default branch)
3656
+ --require-ci-trust <level>
3657
+ refuse the merge, before paying, unless the patch
3658
+ series' head commit has a concluded green CI run at or
3659
+ above this trust level (same gate as \`rig ci status\`)
3660
+ --closes <issue-id> after a successful merge, publish closed (kind:1632)
3661
+ for this issue; repeatable
3652
3662
  --yes skip the confirmation prompt
3653
3663
  --json machine-readable output (without --yes: estimate only)
3654
3664
  --relay <url> ad-hoc relay override (bypasses git remotes)
@@ -3666,6 +3676,8 @@ function parseMergeArgs(args) {
3666
3676
  remote: { type: "string" },
3667
3677
  "repo-id": { type: "string" },
3668
3678
  owner: { type: "string" },
3679
+ "require-ci-trust": { type: "string" },
3680
+ closes: { type: "string", multiple: true },
3669
3681
  standalone: { type: "boolean", default: false },
3670
3682
  "no-daemon": { type: "boolean", default: false },
3671
3683
  help: { type: "boolean", short: "h", default: false }
@@ -3687,8 +3699,23 @@ function parseMergeArgs(args) {
3687
3699
  patchId,
3688
3700
  yes: values.yes === true,
3689
3701
  json: values.json === true,
3690
- relay: values.relay ?? []
3702
+ relay: values.relay ?? [],
3703
+ closes: [...new Set(values.closes ?? [])]
3691
3704
  };
3705
+ for (const id of flags.closes) {
3706
+ if (!HEX64_RE3.test(id)) {
3707
+ throw new Error("--closes must be a 64-character lowercase hex issue id");
3708
+ }
3709
+ }
3710
+ const level = values["require-ci-trust"];
3711
+ if (level !== void 0) {
3712
+ if (!isCiTrustLevel(level)) {
3713
+ throw new Error(
3714
+ `--require-ci-trust must be one of ${CI_TRUST_ORDER.join(" | ")} (got ${JSON.stringify(level)})`
3715
+ );
3716
+ }
3717
+ flags.requireTrust = level;
3718
+ }
3692
3719
  if (values.target !== void 0) flags.target = values.target;
3693
3720
  if (values.remote !== void 0) flags.remote = values.remote;
3694
3721
  if (values["repo-id"] !== void 0) flags.repoId = values["repo-id"];
@@ -3915,6 +3942,23 @@ async function runPrMerge(args, deps) {
3915
3942
  email: `${hexToNpub(identity.pubkey)}@nostr`
3916
3943
  }
3917
3944
  );
3945
+ if (flags.requireTrust !== void 0) {
3946
+ const headCommit = (latest.tags.filter((t) => t[0] === "commit").at(-1)?.[1] ?? applied.newHead).toLowerCase();
3947
+ const gate = await evaluateCiGate({
3948
+ relays,
3949
+ owner,
3950
+ repoId,
3951
+ commit: headCommit,
3952
+ webSocketFactory,
3953
+ requireTrust: flags.requireTrust
3954
+ });
3955
+ if (!gate.ok) {
3956
+ throw new PrMergeError(
3957
+ "ci_gate_failed",
3958
+ `no qualifying green CI run (trust >= ${flags.requireTrust}) for ${headCommit.slice(0, 12)}: ${gate.reason ?? "not green"}. Nothing was pushed, published, or paid.`
3959
+ );
3960
+ }
3961
+ }
3918
3962
  const overlay = new OverlayReader(repoRoot, {
3919
3963
  refname,
3920
3964
  sha: applied.newHead
@@ -3929,12 +3973,17 @@ async function runPrMerge(args, deps) {
3929
3973
  force: false
3930
3974
  });
3931
3975
  const plan = serializePushPlan(pushPlan);
3932
- const total = BigInt(plan.estimate.totalFee) + feeRates.eventFee;
3976
+ const total = BigInt(plan.estimate.totalFee) + feeRates.eventFee * BigInt(1 + flags.closes.length);
3933
3977
  if (!flags.json) {
3934
3978
  for (const line of renderPlan(plan)) io.out(line);
3935
3979
  io.out(
3936
3980
  ` status kind:1631 applied (${applied.commits.length} commit${applied.commits.length === 1 ? "" : "s"}) ${feeRates.eventFee}`
3937
3981
  );
3982
+ if (flags.closes.length > 0) {
3983
+ io.out(
3984
+ ` closes kind:1632 closed (${flags.closes.length} issue${flags.closes.length === 1 ? "" : "s"}) ${feeRates.eventFee * BigInt(flags.closes.length)}`
3985
+ );
3986
+ }
3938
3987
  io.out(` total with status ${total}`);
3939
3988
  io.out(renderIdentityLine(identity));
3940
3989
  }
@@ -3999,6 +4048,25 @@ async function runPrMerge(args, deps) {
3999
4048
  } catch (err) {
4000
4049
  statusError = err instanceof Error ? err.message : String(err);
4001
4050
  }
4051
+ const closed = [];
4052
+ const closeErrors = [];
4053
+ for (const issueId of flags.closes) {
4054
+ try {
4055
+ await ctx.publisher.publishEvent(
4056
+ buildStatus(owner, repoId, issueId, STATUS_CLOSED_KIND2),
4057
+ relays
4058
+ );
4059
+ closed.push(issueId);
4060
+ } catch (err) {
4061
+ closeErrors.push({
4062
+ issueId,
4063
+ error: err instanceof Error ? err.message : String(err)
4064
+ });
4065
+ }
4066
+ }
4067
+ const closeRetryHints = closeErrors.map(
4068
+ (e) => `rig issue close ${e.issueId}`
4069
+ );
4002
4070
  const retryHint = `rig pr status ${root.id} applied`;
4003
4071
  if (flags.json) {
4004
4072
  io.emitJson({
@@ -4010,6 +4078,8 @@ async function runPrMerge(args, deps) {
4010
4078
  revisionId: latest.id,
4011
4079
  target: refname,
4012
4080
  mergedShas: applied.commits,
4081
+ closed,
4082
+ ...closeErrors.length > 0 ? { closeErrors } : {},
4013
4083
  result,
4014
4084
  ...statusEventId !== void 0 ? { statusEventId } : {},
4015
4085
  ...statusError !== void 0 ? {
@@ -4017,6 +4087,11 @@ async function runPrMerge(args, deps) {
4017
4087
  error: "status_publish_failed",
4018
4088
  detail: statusError,
4019
4089
  hint: `the push succeeded but the applied status was not published \u2014 retry with \`${retryHint}\``
4090
+ } : closeErrors.length > 0 ? {
4091
+ partial: true,
4092
+ error: "close_publish_failed",
4093
+ detail: closeErrors.map((e) => `${e.issueId}: ${e.error}`).join("; "),
4094
+ hint: `the push succeeded but some issues were not closed \u2014 retry with ${closeRetryHints.map((h) => `\`${h}\``).join(", ")}`
4020
4095
  } : {}
4021
4096
  });
4022
4097
  } else {
@@ -4027,14 +4102,24 @@ async function runPrMerge(args, deps) {
4027
4102
  );
4028
4103
  }
4029
4104
  }
4105
+ if (!flags.json && closed.length > 0) {
4106
+ io.out(`Closed ${closed.length} issue(s): ${closed.join(", ")}`);
4107
+ }
4030
4108
  if (statusError !== void 0) {
4031
4109
  io.err(
4032
4110
  `partial success: the push succeeded but publishing the applied status failed: ${statusError}`
4033
4111
  );
4034
4112
  io.err(`retry the status with: ${retryHint}`);
4035
- return 1;
4036
4113
  }
4037
- return 0;
4114
+ if (closeErrors.length > 0) {
4115
+ for (const e of closeErrors) {
4116
+ io.err(
4117
+ `partial success: the push succeeded but closing issue ${e.issueId} failed: ${e.error}`
4118
+ );
4119
+ }
4120
+ for (const h of closeRetryHints) io.err(`retry the close with: ${h}`);
4121
+ }
4122
+ return statusError !== void 0 || closeErrors.length > 0 ? 1 : 0;
4038
4123
  } catch (err) {
4039
4124
  return emitCliError(io, flags.json, "pr merge", err);
4040
4125
  } finally {
@@ -4819,7 +4904,7 @@ async function runPrCreate(rest, deps) {
4819
4904
  var STATUS_KIND_BY_VALUE = {
4820
4905
  open: STATUS_OPEN_KIND2,
4821
4906
  applied: STATUS_APPLIED_KIND3,
4822
- closed: STATUS_CLOSED_KIND2,
4907
+ closed: STATUS_CLOSED_KIND3,
4823
4908
  draft: STATUS_DRAFT_KIND2
4824
4909
  };
4825
4910
  function isStatusValue(value) {
@@ -5202,11 +5287,15 @@ Options:
5202
5287
  --json machine-readable envelope (per-chain results array)
5203
5288
  -h, --help show this help`;
5204
5289
  var SHARED_DEVNET_SUFFIX = ".devnet.toonprotocol.dev";
5290
+ var SHARED_DEVNET_HOSTS = /* @__PURE__ */ new Set([
5291
+ "toonprotocol.dev",
5292
+ "relay.toonprotocol.dev"
5293
+ ]);
5205
5294
  function devnetHost(url) {
5206
5295
  if (!url) return void 0;
5207
5296
  try {
5208
5297
  const { hostname } = new URL(url);
5209
- if (hostname.endsWith(SHARED_DEVNET_SUFFIX) || hostname === SHARED_DEVNET_SUFFIX.slice(1)) {
5298
+ if (hostname.endsWith(SHARED_DEVNET_SUFFIX) || hostname === SHARED_DEVNET_SUFFIX.slice(1) || SHARED_DEVNET_HOSTS.has(hostname)) {
5210
5299
  return url;
5211
5300
  }
5212
5301
  } catch {
@@ -5400,7 +5489,8 @@ async function runFund(args, deps) {
5400
5489
  }
5401
5490
  const timeoutEnv = env["TOON_CLIENT_FAUCET_TIMEOUT_MS"];
5402
5491
  const timeoutFor = () => {
5403
- if (timeoutEnv && Number.isFinite(Number(timeoutEnv))) return Number(timeoutEnv);
5492
+ if (timeoutEnv && Number.isFinite(Number(timeoutEnv)))
5493
+ return Number(timeoutEnv);
5404
5494
  if (file.faucetTimeoutMs !== void 0) return file.faucetTimeoutMs;
5405
5495
  return 9e4;
5406
5496
  };
@@ -5428,10 +5518,15 @@ async function runFund(args, deps) {
5428
5518
  }
5429
5519
  const started = Date.now();
5430
5520
  try {
5431
- const { response } = await client.fundWallet(faucetUrl, address, chain, {
5432
- timeout: timeoutFor(),
5433
- ...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
5434
- });
5521
+ const { response } = await client.fundWallet(
5522
+ faucetUrl,
5523
+ address,
5524
+ chain,
5525
+ {
5526
+ timeout: timeoutFor(),
5527
+ ...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
5528
+ }
5529
+ );
5435
5530
  return {
5436
5531
  chain,
5437
5532
  funded: true,
@@ -5477,7 +5572,9 @@ async function runFund(args, deps) {
5477
5572
  }
5478
5573
  }
5479
5574
  io.out(renderIdentityLine(identity));
5480
- io.out("Re-check with `rig balance` (a drip can take a few blocks to land).");
5575
+ io.out(
5576
+ "Re-check with `rig balance` (a drip can take a few blocks to land)."
5577
+ );
5481
5578
  return allFunded ? 0 : 1;
5482
5579
  } catch (err) {
5483
5580
  return emitCliError(io, json, "fund", err);
@@ -5929,7 +6026,7 @@ import {
5929
6026
  PATCH_KIND as PATCH_KIND4,
5930
6027
  REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND4,
5931
6028
  STATUS_APPLIED_KIND as STATUS_APPLIED_KIND4,
5932
- STATUS_CLOSED_KIND as STATUS_CLOSED_KIND3,
6029
+ STATUS_CLOSED_KIND as STATUS_CLOSED_KIND4,
5933
6030
  STATUS_DRAFT_KIND as STATUS_DRAFT_KIND3,
5934
6031
  STATUS_OPEN_KIND as STATUS_OPEN_KIND3
5935
6032
  } from "@toon-protocol/core/nip34";
@@ -6047,7 +6144,7 @@ Options:
6047
6144
  var STATUS_KINDS2 = [
6048
6145
  STATUS_OPEN_KIND3,
6049
6146
  STATUS_APPLIED_KIND4,
6050
- STATUS_CLOSED_KIND3,
6147
+ STATUS_CLOSED_KIND4,
6051
6148
  STATUS_DRAFT_KIND3
6052
6149
  ];
6053
6150
  var CI_KINDS = [
@@ -9253,4 +9350,4 @@ export {
9253
9350
  rigVersion,
9254
9351
  dispatch
9255
9352
  };
9256
- //# sourceMappingURL=chunk-KQ4NQV7T.js.map
9353
+ //# sourceMappingURL=chunk-Z3XRZ5E5.js.map