@toon-protocol/rig 5.2.0 → 5.3.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.
@@ -10,6 +10,7 @@ import {
10
10
  InvalidRelayUrlError,
11
11
  MultiUrlRemoteError,
12
12
  NotAGitRepositoryError,
13
+ PrMergeError,
13
14
  RESERVED_SECRET_NAMES,
14
15
  SECRET_NAME_RE,
15
16
  UnconfiguredRepoAddressError,
@@ -57,13 +58,13 @@ import {
57
58
  updateRef,
58
59
  writeGitObjects,
59
60
  writeToonConfig
60
- } from "./chunk-S5R44MMB.js";
61
+ } from "./chunk-DGF7WCRW.js";
61
62
  import {
62
63
  PREFERRED_GATEWAY,
63
64
  mirrorGatewaysFor,
64
65
  readGateways,
65
66
  shaResolverFor
66
- } from "./chunk-FX5GPZYU.js";
67
+ } from "./chunk-UXRWMKXV.js";
67
68
  import {
68
69
  COMMENT_KIND,
69
70
  DEFAULT_KEYSTORE_PASSWORD,
@@ -92,7 +93,7 @@ import {
92
93
  resolveIdentity,
93
94
  revisionRootId,
94
95
  selectRevision
95
- } from "./chunk-JX5P2KAA.js";
96
+ } from "./chunk-OVZJ5P6E.js";
96
97
  import {
97
98
  ChannelMapStore,
98
99
  channelStatus,
@@ -321,7 +322,7 @@ function loadPaidSession(deps, relayUrl) {
321
322
  });
322
323
  }
323
324
  var defaultLoadStandalone = async (options) => {
324
- const mod = await import("./standalone-mode-NWCCRFCL.js");
325
+ const mod = await import("./standalone-mode-E7TNMWGO.js");
325
326
  return mod.createStandaloneContext(options);
326
327
  };
327
328
  function identityReport(ctx) {
@@ -2306,9 +2307,9 @@ async function runCiTrigger(args, deps) {
2306
2307
  });
2307
2308
  }
2308
2309
  async function gitShowBytes(repoRoot, commit, path) {
2309
- const { execFile } = await import("child_process");
2310
+ const { execFile: execFile2 } = await import("child_process");
2310
2311
  return new Promise((resolve2, reject) => {
2311
- execFile(
2312
+ execFile2(
2312
2313
  "git",
2313
2314
  ["show", `${commit}:${path}`],
2314
2315
  { cwd: repoRoot, encoding: "buffer", maxBuffer: 16 * 1024 * 1024 },
@@ -2519,7 +2520,7 @@ async function runCi(args, deps) {
2519
2520
  case "status":
2520
2521
  return runCiStatus(rest, deps);
2521
2522
  case "serve":
2522
- return (await import("./ci-serve-CA37KQVC.js")).runCiServe(rest, deps);
2523
+ return (await import("./ci-serve-R7ZQ7GJQ.js")).runCiServe(rest, deps);
2523
2524
  case "--help":
2524
2525
  case "-h":
2525
2526
  case "help":
@@ -2790,18 +2791,257 @@ async function runClone(args, deps) {
2790
2791
 
2791
2792
  // src/cli/events.ts
2792
2793
  import { readFile } from "fs/promises";
2793
- import { parseArgs as parseArgs8 } from "util";
2794
+ import { parseArgs as parseArgs10 } from "util";
2794
2795
  import {
2795
- PATCH_KIND as PATCH_KIND2,
2796
- REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND2,
2797
- STATUS_APPLIED_KIND as STATUS_APPLIED_KIND2,
2796
+ PATCH_KIND as PATCH_KIND3,
2797
+ REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND3,
2798
+ STATUS_APPLIED_KIND as STATUS_APPLIED_KIND3,
2798
2799
  STATUS_CLOSED_KIND as STATUS_CLOSED_KIND2,
2799
2800
  STATUS_DRAFT_KIND as STATUS_DRAFT_KIND2,
2800
2801
  STATUS_OPEN_KIND as STATUS_OPEN_KIND2
2801
2802
  } from "@toon-protocol/core/nip34";
2802
2803
 
2803
- // src/cli/tracker.ts
2804
+ // src/cli/merge.ts
2805
+ import { execFile } from "child_process";
2806
+ import { mkdtemp as mkdtemp2, rm as rm2, writeFile } from "fs/promises";
2807
+ import { tmpdir } from "os";
2808
+ import { join as join4 } from "path";
2809
+ import { parseArgs as parseArgs9 } from "util";
2810
+ import { promisify } from "util";
2811
+ import {
2812
+ PATCH_KIND as PATCH_KIND2,
2813
+ REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND2,
2814
+ STATUS_APPLIED_KIND as STATUS_APPLIED_KIND2
2815
+ } from "@toon-protocol/core/nip34";
2816
+
2817
+ // src/cli/fetch.ts
2804
2818
  import { parseArgs as parseArgs7 } from "util";
2819
+ var FETCH_USAGE = `Usage: rig fetch [remote] [options]
2820
+
2821
+ Fetch from a TOON remote \u2014 FREE (relay reads + Arweave gateway downloads; no
2822
+ payments, no identity needed). Reads the kind:30618 repository state from the
2823
+ remote's relay, downloads only the git objects this repository is missing
2824
+ (SHA-1 verified), and updates the remote-tracking refs
2825
+ (refs/remotes/<remote>/*; tags land at refs/tags/*), reporting what moved.
2826
+
2827
+ No merge happens: integrate with the git passthrough, e.g.
2828
+ \`rig merge origin/main\`. \`rig fetch\` is the TOON transport and shadows
2829
+ \`git fetch\` \u2014 plain-git fetches remain available via \`git fetch\` directly.
2830
+
2831
+ The repo address (toon.repoid/toon.owner) comes from the config \`rig init\`
2832
+ or \`rig clone\` writes; --repo-id/--owner override.
2833
+
2834
+ Options:
2835
+ --repo-id <id> repository id / NIP-34 d-tag (default: git config)
2836
+ --owner <pubkey> repository owner (npub or 64-char hex; default: git config)
2837
+ --relay <url> ad-hoc relay override \u2014 bypasses the remote's URL
2838
+ --gateway <url> gateway to read objects through FIRST, on its raw-bytes
2839
+ route <url>/raw/<txId>, ahead of the public gateway
2840
+ list \u2014 name a private, local or air-gapped gateway to
2841
+ fetch objects the public ones do not carry
2842
+ (env RIG_ARWEAVE_GATEWAY also sets it)
2843
+ --concurrency <n> parallel gateway downloads (default 8)
2844
+ --json machine-readable result envelope
2845
+ -h, --help show this help`;
2846
+ var WS_URL_RE3 = /^wss?:\/\//i;
2847
+ function localRefFor(refname, remote) {
2848
+ if (refname.startsWith("refs/heads/")) {
2849
+ return `refs/remotes/${remote}/${refname.slice("refs/heads/".length)}`;
2850
+ }
2851
+ if (refname.startsWith("refs/tags/")) return refname;
2852
+ return null;
2853
+ }
2854
+ async function resolveLocalRef(repoRoot, refname) {
2855
+ try {
2856
+ const out = await runGit(repoRoot, [
2857
+ "rev-parse",
2858
+ "--verify",
2859
+ "--quiet",
2860
+ refname
2861
+ ]);
2862
+ const sha = out.trim();
2863
+ return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
2864
+ } catch {
2865
+ return null;
2866
+ }
2867
+ }
2868
+ async function runFetch(args, deps) {
2869
+ const { io } = deps;
2870
+ let json = false;
2871
+ let remote = "origin";
2872
+ let relayFlag;
2873
+ let repoIdFlag;
2874
+ let ownerFlag;
2875
+ let gatewayFlag;
2876
+ let concurrency;
2877
+ try {
2878
+ const { values, positionals } = parseArgs7({
2879
+ args,
2880
+ options: {
2881
+ json: { type: "boolean", default: false },
2882
+ relay: { type: "string" },
2883
+ "repo-id": { type: "string" },
2884
+ owner: { type: "string" },
2885
+ gateway: { type: "string" },
2886
+ concurrency: { type: "string" },
2887
+ help: { type: "boolean", short: "h", default: false }
2888
+ },
2889
+ allowPositionals: true
2890
+ });
2891
+ if (values.help) {
2892
+ io.out(FETCH_USAGE);
2893
+ return 0;
2894
+ }
2895
+ json = values.json === true;
2896
+ if (positionals.length > 1) {
2897
+ throw new Error(
2898
+ `expected at most one [remote] argument, got ${positionals.length}`
2899
+ );
2900
+ }
2901
+ if (positionals[0] !== void 0) remote = positionals[0];
2902
+ relayFlag = values.relay;
2903
+ repoIdFlag = values["repo-id"];
2904
+ ownerFlag = values.owner !== void 0 ? ownerToHex(values.owner) : void 0;
2905
+ gatewayFlag = values.gateway;
2906
+ if (values.concurrency !== void 0) {
2907
+ concurrency = Number.parseInt(values.concurrency, 10);
2908
+ if (!Number.isSafeInteger(concurrency) || concurrency < 1) {
2909
+ throw new Error("--concurrency must be a positive integer");
2910
+ }
2911
+ }
2912
+ } catch (err) {
2913
+ io.err(err instanceof Error ? err.message : String(err));
2914
+ io.err(FETCH_USAGE);
2915
+ return 2;
2916
+ }
2917
+ try {
2918
+ const repoRoot = await resolveRepoRoot(deps.cwd);
2919
+ const toonConfig = await readToonConfig(repoRoot);
2920
+ const repoId = repoIdFlag ?? toonConfig.repoId;
2921
+ if (!repoId) throw new UnconfiguredRepoAddressError("repository id");
2922
+ const owner = ownerFlag ?? toonConfig.owner;
2923
+ if (!owner) throw new UnconfiguredRepoAddressError("repository owner");
2924
+ let relayUrl;
2925
+ if (relayFlag !== void 0) {
2926
+ relayUrl = relayFlag;
2927
+ } else {
2928
+ const urls = await getGitRemoteUrls(repoRoot, remote);
2929
+ if (urls.length === 0) throw new UnknownRemoteError(remote);
2930
+ if (urls.length > 1) throw new MultiUrlRemoteError(remote, urls);
2931
+ relayUrl = urls[0];
2932
+ }
2933
+ if (!WS_URL_RE3.test(relayUrl)) {
2934
+ throw new InvalidRelayUrlError(
2935
+ relayUrl,
2936
+ `remote ${JSON.stringify(remote)}`
2937
+ );
2938
+ }
2939
+ const remoteState = await fetchRemoteState({
2940
+ relayUrls: [relayUrl],
2941
+ ownerPubkey: owner,
2942
+ repoId,
2943
+ ...deps.webSocketFactory ? { webSocketFactory: deps.webSocketFactory } : {},
2944
+ // The GraphQL fallback for SHAs the map does not cover asks the SAME
2945
+ // permaweb the objects are read from (#183).
2946
+ resolveSha: deps.resolveSha ?? shaResolverFor(gatewayFlag, deps.env)
2947
+ });
2948
+ const planned = [];
2949
+ for (const [refname, sha] of remoteState.refs) {
2950
+ if (!isSafeRefname(refname)) {
2951
+ io.err(
2952
+ `warning: skipping unsafe ref name from relay: ${JSON.stringify(refname)}`
2953
+ );
2954
+ continue;
2955
+ }
2956
+ const localRef = localRefFor(refname, remote);
2957
+ if (localRef === null) {
2958
+ io.err(
2959
+ `warning: skipping ref outside refs/heads and refs/tags: ${refname}`
2960
+ );
2961
+ continue;
2962
+ }
2963
+ planned.push({ refname, localRef, newSha: sha });
2964
+ }
2965
+ const reader = new GitRepoReader(repoRoot);
2966
+ const tips = [...new Set(planned.map((p) => p.newSha))];
2967
+ const presentLocally = new Set(await reader.listAllObjectShas());
2968
+ const collected = await collectRepoObjects({
2969
+ tips,
2970
+ shaToTxId: remoteState.shaToTxId,
2971
+ resolveMissing: (shas) => remoteState.resolveMissing(shas),
2972
+ presentLocally,
2973
+ // `--gateway` / RIG_ARWEAVE_GATEWAY first, public list behind it (#176).
2974
+ gateways: readGateways(gatewayFlag, deps.env),
2975
+ ...deps.fetchFn ? { fetchFn: deps.fetchFn } : {},
2976
+ ...concurrency !== void 0 ? { concurrency } : {}
2977
+ });
2978
+ if (collected.missing.length > 0) {
2979
+ throw new MissingRemoteObjectsError(
2980
+ collected.missing,
2981
+ `cannot fetch from ${relayUrl}`
2982
+ );
2983
+ }
2984
+ const written = await writeGitObjects(repoRoot, collected.objects.values());
2985
+ const updates = [];
2986
+ for (const { refname, localRef, newSha } of planned) {
2987
+ const oldSha = await resolveLocalRef(repoRoot, localRef);
2988
+ if (oldSha === newSha) {
2989
+ updates.push({ refname, localRef, oldSha, newSha, kind: "up-to-date" });
2990
+ continue;
2991
+ }
2992
+ let kind;
2993
+ if (oldSha === null) {
2994
+ kind = "new";
2995
+ } else {
2996
+ kind = await reader.isAncestor(oldSha, newSha) ? "fast-forward" : "forced";
2997
+ }
2998
+ await updateRef(repoRoot, localRef, newSha);
2999
+ updates.push({ refname, localRef, oldSha, newSha, kind });
3000
+ }
3001
+ const moved = updates.filter((u) => u.kind !== "up-to-date");
3002
+ if (json) {
3003
+ io.emitJson({
3004
+ command: "fetch",
3005
+ repoAddr: { ownerPubkey: owner, repoId },
3006
+ remote,
3007
+ relay: relayUrl,
3008
+ objectsDownloaded: written,
3009
+ updates,
3010
+ executed: true
3011
+ });
3012
+ return 0;
3013
+ }
3014
+ if (moved.length === 0) {
3015
+ io.out("Already up to date.");
3016
+ return 0;
3017
+ }
3018
+ io.out(`From ${relayUrl}`);
3019
+ for (const u of moved) {
3020
+ const short = (refname) => refname.replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/^refs\/remotes\//, "");
3021
+ const src = short(u.refname);
3022
+ const dst = short(u.localRef);
3023
+ if (u.kind === "new") {
3024
+ const label = u.refname.startsWith("refs/tags/") ? "[new tag]" : "[new branch]";
3025
+ io.out(` * ${label.padEnd(17)} ${src.padEnd(14)} -> ${dst}`);
3026
+ } else if (u.kind === "forced") {
3027
+ io.out(
3028
+ ` + ${u.oldSha.slice(0, 7)}...${u.newSha.slice(0, 7)} ${src.padEnd(14)} -> ${dst} (forced update)`
3029
+ );
3030
+ } else {
3031
+ io.out(
3032
+ ` ${u.oldSha.slice(0, 7)}..${u.newSha.slice(0, 7)} ${src.padEnd(14)} -> ${dst}`
3033
+ );
3034
+ }
3035
+ }
3036
+ io.out(`Downloaded ${written} object(s) (SHA-1 verified).`);
3037
+ return 0;
3038
+ } catch (err) {
3039
+ return emitCliError(io, json, "fetch", err);
3040
+ }
3041
+ }
3042
+
3043
+ // src/cli/tracker.ts
3044
+ import { parseArgs as parseArgs8 } from "util";
2805
3045
  import {
2806
3046
  ISSUE_KIND,
2807
3047
  PATCH_KIND,
@@ -2887,7 +3127,7 @@ function withTargetAuthor(authorized, targetAuthorPubkey) {
2887
3127
  }
2888
3128
  var RELAY_TIMEOUT_MS = 1e4;
2889
3129
  var HEX64_RE2 = /^[0-9a-f]{64}$/;
2890
- var WS_URL_RE3 = /^wss?:\/\//i;
3130
+ var WS_URL_RE4 = /^wss?:\/\//i;
2891
3131
  function defaultWebSocketFactory2(url) {
2892
3132
  const ctor = globalThis.WebSocket;
2893
3133
  if (!ctor) {
@@ -2971,7 +3211,7 @@ async function resolveTrackerContext(flags, deps, needRepoAddr) {
2971
3211
  repoRoot,
2972
3212
  toonRelays: toonConfig.relays
2973
3213
  });
2974
- const wsRelays = resolved.relays.filter((url) => WS_URL_RE3.test(url));
3214
+ const wsRelays = resolved.relays.filter((url) => WS_URL_RE4.test(url));
2975
3215
  if (wsRelays.length === 0) {
2976
3216
  throw new InvalidRelayUrlError(
2977
3217
  resolved.relays[0] ?? "",
@@ -3198,7 +3438,7 @@ async function runList(args, deps, spec) {
3198
3438
  const { io } = deps;
3199
3439
  let flags;
3200
3440
  try {
3201
- const { values, positionals } = parseArgs7({
3441
+ const { values, positionals } = parseArgs8({
3202
3442
  args,
3203
3443
  options: TRACKER_OPTIONS,
3204
3444
  allowPositionals: true
@@ -3263,7 +3503,7 @@ async function runShow(args, deps, spec) {
3263
3503
  let flags;
3264
3504
  let eventId;
3265
3505
  try {
3266
- const { values, positionals } = parseArgs7({
3506
+ const { values, positionals } = parseArgs8({
3267
3507
  args,
3268
3508
  options: TRACKER_OPTIONS,
3269
3509
  allowPositionals: true
@@ -3391,6 +3631,435 @@ function runPrShow(args, deps) {
3391
3631
  });
3392
3632
  }
3393
3633
 
3634
+ // src/cli/merge.ts
3635
+ var execFileAsync = promisify(execFile);
3636
+ var HEX64_RE3 = /^[0-9a-f]{64}$/;
3637
+ var PR_MERGE_USAGE = `Usage: rig pr merge <patch-id> [--target <branch>] [options]
3638
+
3639
+ Apply the latest authorized revision of a patch with \`git am\` onto the
3640
+ honored tip of the target branch, push the result, and publish an applied
3641
+ status (kind:1631) naming the new commit SHAs \u2014 in that order, so the status
3642
+ never claims a merge that did not happen. A paid command; writes are permanent
3643
+ and non-refundable. Only the owner or a declared maintainer may merge.
3644
+
3645
+ If the patch does not apply, nothing is spent and your working tree is left as
3646
+ it was. If the push succeeds but the status publish fails, the merge is
3647
+ reported as a partial success; retry with \`rig pr status <patch-id> applied\`.
3648
+
3649
+ Options:
3650
+ --target <branch> branch to merge onto (default: the patch's branch-name
3651
+ tag, else the repo's default branch)
3652
+ --yes skip the confirmation prompt
3653
+ --json machine-readable output (without --yes: estimate only)
3654
+ --relay <url> ad-hoc relay override (bypasses git remotes)
3655
+ --remote <name> git remote to use (default: origin)
3656
+ --repo-id <id> repository id (default: git config toon.repoid)
3657
+ --owner <pubkey> repository owner (default: git config toon.owner)`;
3658
+ function parseMergeArgs(args) {
3659
+ const { values, positionals } = parseArgs9({
3660
+ args,
3661
+ options: {
3662
+ target: { type: "string" },
3663
+ yes: { type: "boolean", default: false },
3664
+ json: { type: "boolean", default: false },
3665
+ relay: { type: "string", multiple: true },
3666
+ remote: { type: "string" },
3667
+ "repo-id": { type: "string" },
3668
+ owner: { type: "string" },
3669
+ standalone: { type: "boolean", default: false },
3670
+ "no-daemon": { type: "boolean", default: false },
3671
+ help: { type: "boolean", short: "h", default: false }
3672
+ },
3673
+ allowPositionals: true
3674
+ });
3675
+ if (values.help) return "help";
3676
+ if (positionals.length !== 1) {
3677
+ throw new Error("expected exactly one argument: <patch-id>");
3678
+ }
3679
+ const patchId = positionals[0];
3680
+ if (!HEX64_RE3.test(patchId)) {
3681
+ throw new Error("<patch-id> must be a 64-character lowercase hex event id");
3682
+ }
3683
+ if (values.owner !== void 0 && !HEX64_RE3.test(values.owner)) {
3684
+ throw new Error("--owner must be a 64-character lowercase hex pubkey");
3685
+ }
3686
+ const flags = {
3687
+ patchId,
3688
+ yes: values.yes === true,
3689
+ json: values.json === true,
3690
+ relay: values.relay ?? []
3691
+ };
3692
+ if (values.target !== void 0) flags.target = values.target;
3693
+ if (values.remote !== void 0) flags.remote = values.remote;
3694
+ if (values["repo-id"] !== void 0) flags.repoId = values["repo-id"];
3695
+ if (values.owner !== void 0) flags.owner = values.owner;
3696
+ return flags;
3697
+ }
3698
+ async function git(cwd, args, env) {
3699
+ const { stdout } = await execFileAsync("git", args, {
3700
+ cwd,
3701
+ encoding: "utf-8",
3702
+ maxBuffer: 64 * 1024 * 1024,
3703
+ ...env ? { env } : {}
3704
+ });
3705
+ return stdout.trim();
3706
+ }
3707
+ async function gitOk(cwd, args) {
3708
+ try {
3709
+ await git(cwd, args);
3710
+ return true;
3711
+ } catch {
3712
+ return false;
3713
+ }
3714
+ }
3715
+ function gitFailure(err) {
3716
+ const e = err;
3717
+ return (e.stderr || e.stdout || e.message || String(err)).trim();
3718
+ }
3719
+ var OverlayReader = class extends GitRepoReader {
3720
+ constructor(repoPath, overlay) {
3721
+ super(repoPath);
3722
+ this.overlay = overlay;
3723
+ }
3724
+ overlay;
3725
+ async listRefs() {
3726
+ const base = await super.listRefs();
3727
+ const refs = base.refs.filter(
3728
+ (r) => r.refname !== this.overlay.refname
3729
+ );
3730
+ refs.push({
3731
+ refname: this.overlay.refname,
3732
+ sha: this.overlay.sha,
3733
+ type: "commit"
3734
+ });
3735
+ return { ...base, refs };
3736
+ }
3737
+ };
3738
+ async function applyInIsolation(repoRoot, tip, patchText, committer) {
3739
+ const scratch = await mkdtemp2(join4(tmpdir(), "rig-merge-"));
3740
+ const worktree = join4(scratch, "wt");
3741
+ try {
3742
+ await git(repoRoot, ["worktree", "add", "--detach", worktree, tip]);
3743
+ const patchFile = join4(scratch, "patch.mbox");
3744
+ await writeFile(patchFile, patchText, "utf-8");
3745
+ const env = { ...process.env };
3746
+ if (committer) {
3747
+ env["GIT_COMMITTER_NAME"] = committer.name;
3748
+ env["GIT_COMMITTER_EMAIL"] = committer.email;
3749
+ }
3750
+ try {
3751
+ await git(worktree, ["am", "--quiet", patchFile], env);
3752
+ } catch (err) {
3753
+ await git(worktree, ["am", "--abort"]).catch(() => void 0);
3754
+ throw new PrMergeError(
3755
+ "apply_conflict",
3756
+ `the patch does not apply cleanly onto ${tip.slice(0, 7)} \u2014 ask the contributor for a revision (\`rig pr create --revises\`). Nothing was pushed, published, or paid, and your working tree is unchanged.
3757
+ ` + gitFailure(err)
3758
+ );
3759
+ }
3760
+ const newHead = await git(worktree, ["rev-parse", "HEAD"]);
3761
+ const listed = await git(worktree, [
3762
+ "rev-list",
3763
+ "--reverse",
3764
+ `${tip}..${newHead}`
3765
+ ]);
3766
+ const commits = listed === "" ? [] : listed.split("\n");
3767
+ if (commits.length === 0) {
3768
+ throw new PrMergeError(
3769
+ "nothing_to_apply",
3770
+ "the patch applied no commits (already merged?) \u2014 nothing was pushed, published, or paid."
3771
+ );
3772
+ }
3773
+ return { newHead, commits };
3774
+ } finally {
3775
+ await git(repoRoot, ["worktree", "remove", "--force", worktree]).catch(
3776
+ () => void 0
3777
+ );
3778
+ await git(repoRoot, ["worktree", "prune"]).catch(() => void 0);
3779
+ await rm2(scratch, { recursive: true, force: true });
3780
+ }
3781
+ }
3782
+ var BRANCH_PREFIX = "refs/heads/";
3783
+ async function runPrMerge(args, deps) {
3784
+ const { io } = deps;
3785
+ let flags;
3786
+ try {
3787
+ const parsed = parseMergeArgs(args);
3788
+ if (parsed === "help") {
3789
+ io.out(PR_MERGE_USAGE);
3790
+ return 0;
3791
+ }
3792
+ flags = parsed;
3793
+ } catch (err) {
3794
+ io.err(err instanceof Error ? err.message : String(err));
3795
+ io.err(PR_MERGE_USAGE);
3796
+ return 2;
3797
+ }
3798
+ deps = withForcedStandalone(deps);
3799
+ const webSocketFactory = deps.webSocketFactory ?? defaultWebSocketFactory;
3800
+ let stop;
3801
+ try {
3802
+ const repoRoot = await resolveRepoRoot(deps.cwd);
3803
+ const toonConfig = await readToonConfig(repoRoot);
3804
+ const repoId = flags.repoId ?? toonConfig.repoId;
3805
+ if (!repoId) throw new UnconfiguredRepoAddressError("repository id");
3806
+ const resolved = await resolveRelays({
3807
+ relayFlags: flags.relay,
3808
+ remoteName: flags.remote,
3809
+ repoRoot,
3810
+ toonRelays: toonConfig.relays
3811
+ });
3812
+ if (resolved.nudge !== void 0) io.err(resolved.nudge);
3813
+ const relays = resolved.relays;
3814
+ if (relays.length > 1) {
3815
+ io.err(singleRelayRefusal(resolved, "Nothing was pushed or paid."));
3816
+ return 1;
3817
+ }
3818
+ const relay = relays[0];
3819
+ const session = await loadPaidSession(deps, relay);
3820
+ if (session.path !== "standalone") {
3821
+ throw new Error("internal: rig pr merge requires the standalone session");
3822
+ }
3823
+ const ctx = session.ctx;
3824
+ stop = () => ctx.stop();
3825
+ const identity = identityReport(ctx);
3826
+ const owner = flags.owner ?? toonConfig.owner ?? identity.pubkey;
3827
+ const addr = { ownerPubkey: owner, repoId };
3828
+ const aTag = `${REPOSITORY_ANNOUNCEMENT_KIND2}:${owner}:${repoId}`;
3829
+ const lookup = async (id) => (await queryAll(relays, [{ ids: [id] }], webSocketFactory)).get(id);
3830
+ let root = await lookup(flags.patchId);
3831
+ if (root && root.kind === PATCH_KIND2 && isPatchRevision(root)) {
3832
+ const rootId = revisionRootId(root);
3833
+ if (rootId !== void 0) root = await lookup(rootId);
3834
+ }
3835
+ if (!root || root.kind !== PATCH_KIND2) {
3836
+ throw new PrMergeError(
3837
+ "patch_not_found",
3838
+ `patch ${flags.patchId} not found as a kind:1617 patch on ${relay} \u2014 nothing was pushed or paid`
3839
+ );
3840
+ }
3841
+ if (!root.tags.some((t) => t[0] === "a" && t[1] === aTag)) {
3842
+ throw new PrMergeError(
3843
+ "patch_not_found",
3844
+ `patch ${root.id} does not belong to ${aTag} \u2014 nothing was pushed or paid`
3845
+ );
3846
+ }
3847
+ const remote = await ctx.fetchRemote({
3848
+ ownerPubkey: owner,
3849
+ repoId,
3850
+ relayUrls: relays
3851
+ });
3852
+ const authorized = authorizedAuthors(
3853
+ owner,
3854
+ remote.announceEvent?.tags ?? []
3855
+ );
3856
+ const revisionEvents = await queryAll(
3857
+ relays,
3858
+ [{ kinds: [PATCH_KIND2], "#e": [root.id] }],
3859
+ webSocketFactory
3860
+ );
3861
+ const { latest } = selectRevision(
3862
+ root,
3863
+ [...revisionEvents.values()].filter((e) => e.kind === PATCH_KIND2),
3864
+ authorized
3865
+ );
3866
+ if (!authorized.has(identity.pubkey.toLowerCase())) {
3867
+ throw new PrMergeError(
3868
+ "not_authorized",
3869
+ `only the owner or a declared maintainer can merge \u2014 ${identity.pubkey.slice(0, 8)}\u2026 is neither for ${aTag}. Readers would ignore the pushed state. Nothing was pushed or paid.`
3870
+ );
3871
+ }
3872
+ if (!remote.announced) {
3873
+ throw new PrMergeError(
3874
+ "target_not_found",
3875
+ `${aTag} is not announced on ${relay} \u2014 nothing to merge onto`
3876
+ );
3877
+ }
3878
+ const branch = (flags.target ?? firstTagValue(latest.tags, "branch-name") ?? remote.headSymref ?? "main").replace(/^refs\/heads\//, "");
3879
+ const refname = `${BRANCH_PREFIX}${branch}`;
3880
+ const tip = remote.refs.get(refname);
3881
+ if (tip === void 0) {
3882
+ throw new PrMergeError(
3883
+ "target_not_found",
3884
+ `branch ${JSON.stringify(branch)} is not in the honored repo state (${[...remote.refs.keys()].join(", ") || "no refs"}) \u2014 pass --target. Nothing was pushed or paid.`
3885
+ );
3886
+ }
3887
+ if (!await gitOk(repoRoot, ["cat-file", "-e", `${tip}^{commit}`])) {
3888
+ await runFetch(
3889
+ ["--relay", relay, "--owner", owner, "--repo-id", repoId],
3890
+ { ...deps, io: { ...io, out: () => void 0 } }
3891
+ );
3892
+ if (!await gitOk(repoRoot, ["cat-file", "-e", `${tip}^{commit}`])) {
3893
+ throw new PrMergeError(
3894
+ "tip_unavailable",
3895
+ `the honored tip ${tip.slice(0, 7)} of ${branch} could not be fetched \u2014 run \`rig fetch\` and retry. Nothing was pushed or paid.`
3896
+ );
3897
+ }
3898
+ }
3899
+ const reader = new GitRepoReader(repoRoot);
3900
+ const localRefs = (await reader.listRefs()).refs;
3901
+ const localSha = localRefs.find((r) => r.refname === refname)?.sha;
3902
+ if (localSha !== void 0 && localSha !== tip && !await reader.isAncestor(localSha, tip)) {
3903
+ throw new PrMergeError(
3904
+ "local_branch_diverged",
3905
+ `local ${branch} (${localSha.slice(0, 7)}) is not behind the honored tip (${tip.slice(0, 7)}) \u2014 push or reset it first. Nothing was pushed or paid.`
3906
+ );
3907
+ }
3908
+ const hasCommitter = await gitOk(repoRoot, ["config", "user.email"]);
3909
+ const applied = await applyInIsolation(
3910
+ repoRoot,
3911
+ tip,
3912
+ latest.content,
3913
+ hasCommitter ? void 0 : {
3914
+ name: hexToNpub(identity.pubkey),
3915
+ email: `${hexToNpub(identity.pubkey)}@nostr`
3916
+ }
3917
+ );
3918
+ const overlay = new OverlayReader(repoRoot, {
3919
+ refname,
3920
+ sha: applied.newHead
3921
+ });
3922
+ const feeRates = await ctx.publisher.getFeeRates();
3923
+ const pushPlan = await planPush({
3924
+ repoReader: overlay,
3925
+ remoteState: remote,
3926
+ feeRates,
3927
+ repoId,
3928
+ refs: [refname],
3929
+ force: false
3930
+ });
3931
+ const plan = serializePushPlan(pushPlan);
3932
+ const total = BigInt(plan.estimate.totalFee) + feeRates.eventFee;
3933
+ if (!flags.json) {
3934
+ for (const line of renderPlan(plan)) io.out(line);
3935
+ io.out(
3936
+ ` status kind:1631 applied (${applied.commits.length} commit${applied.commits.length === 1 ? "" : "s"}) ${feeRates.eventFee}`
3937
+ );
3938
+ io.out(` total with status ${total}`);
3939
+ io.out(renderIdentityLine(identity));
3940
+ }
3941
+ if (!flags.yes) {
3942
+ if (flags.json) {
3943
+ io.emitJson({
3944
+ command: "pr merge",
3945
+ repoAddr: addr,
3946
+ identity,
3947
+ executed: false,
3948
+ patchId: root.id,
3949
+ revisionId: latest.id,
3950
+ target: refname,
3951
+ mergedShas: applied.commits,
3952
+ plan,
3953
+ totalFee: total.toString(),
3954
+ hint: "estimate only \u2014 re-run with --yes to push and publish (permanent, non-refundable)"
3955
+ });
3956
+ return 0;
3957
+ }
3958
+ if (!io.isInteractive) {
3959
+ io.err(
3960
+ "refusing to spend channel funds without confirmation in a non-interactive session \u2014 re-run with --yes (or use --json for an estimate)"
3961
+ );
3962
+ return 1;
3963
+ }
3964
+ const proceed = await io.confirm(
3965
+ `Proceed with paid merge (total ${total} base units)? [y/N] `
3966
+ );
3967
+ if (!proceed) {
3968
+ io.err("aborted \u2014 nothing was pushed or published.");
3969
+ return 1;
3970
+ }
3971
+ }
3972
+ const pushResult = await executePush({
3973
+ plan: pushPlan,
3974
+ publisher: ctx.publisher,
3975
+ remoteState: remote,
3976
+ repoReader: overlay,
3977
+ relayUrls: relays
3978
+ });
3979
+ const result = serializePushResult(pushPlan, pushResult);
3980
+ const localNote = await advanceLocalBranch(
3981
+ repoRoot,
3982
+ reader,
3983
+ refname,
3984
+ applied.newHead,
3985
+ localSha
3986
+ );
3987
+ if (localNote !== void 0) io.err(localNote);
3988
+ let statusEventId;
3989
+ let statusError;
3990
+ try {
3991
+ const receipt = await ctx.publisher.publishEvent(
3992
+ buildStatus(owner, repoId, root.id, STATUS_APPLIED_KIND2, root.pubkey, {
3993
+ commits: applied.commits,
3994
+ revisionEventId: latest.id
3995
+ }),
3996
+ relays
3997
+ );
3998
+ statusEventId = receipt.eventId;
3999
+ } catch (err) {
4000
+ statusError = err instanceof Error ? err.message : String(err);
4001
+ }
4002
+ const retryHint = `rig pr status ${root.id} applied`;
4003
+ if (flags.json) {
4004
+ io.emitJson({
4005
+ command: "pr merge",
4006
+ repoAddr: addr,
4007
+ identity,
4008
+ executed: true,
4009
+ patchId: root.id,
4010
+ revisionId: latest.id,
4011
+ target: refname,
4012
+ mergedShas: applied.commits,
4013
+ result,
4014
+ ...statusEventId !== void 0 ? { statusEventId } : {},
4015
+ ...statusError !== void 0 ? {
4016
+ partial: true,
4017
+ error: "status_publish_failed",
4018
+ detail: statusError,
4019
+ hint: `the push succeeded but the applied status was not published \u2014 retry with \`${retryHint}\``
4020
+ } : {}
4021
+ });
4022
+ } else {
4023
+ for (const line of renderResult(result)) io.out(line);
4024
+ if (statusEventId !== void 0) {
4025
+ io.out(
4026
+ `Merged ${applied.commits.length} commit(s) onto ${branch}; applied status ${statusEventId}`
4027
+ );
4028
+ }
4029
+ }
4030
+ if (statusError !== void 0) {
4031
+ io.err(
4032
+ `partial success: the push succeeded but publishing the applied status failed: ${statusError}`
4033
+ );
4034
+ io.err(`retry the status with: ${retryHint}`);
4035
+ return 1;
4036
+ }
4037
+ return 0;
4038
+ } catch (err) {
4039
+ return emitCliError(io, flags.json, "pr merge", err);
4040
+ } finally {
4041
+ if (stop) await stop().catch(() => void 0);
4042
+ }
4043
+ }
4044
+ async function advanceLocalBranch(repoRoot, reader, refname, newHead, oldSha) {
4045
+ try {
4046
+ const { head } = await reader.listRefs();
4047
+ if (head === refname) {
4048
+ await git(repoRoot, ["merge", "--ff-only", newHead]);
4049
+ } else {
4050
+ await git(repoRoot, [
4051
+ "update-ref",
4052
+ refname,
4053
+ newHead,
4054
+ oldSha ?? "0".repeat(40)
4055
+ ]);
4056
+ }
4057
+ return void 0;
4058
+ } catch (err) {
4059
+ return `warning: the push succeeded but local ${refname} could not be moved to ${newHead.slice(0, 7)}: ${gitFailure(err)} \u2014 run \`rig fetch\``;
4060
+ }
4061
+ }
4062
+
3394
4063
  // src/cli/events.ts
3395
4064
  var defaultReadStdin2 = async () => {
3396
4065
  if (process.stdin.isTTY) return "";
@@ -3512,14 +4181,16 @@ Options:
3512
4181
  ${COMMON_FLAGS_USAGE2}`;
3513
4182
  var PR_USAGE = `${PR_CREATE_USAGE}
3514
4183
 
4184
+ ${PR_MERGE_USAGE}
4185
+
3515
4186
  ${PR_STATUS_USAGE}
3516
4187
 
3517
4188
  ${PR_LIST_USAGE}
3518
4189
 
3519
4190
  ${PR_SHOW_USAGE}`;
3520
- var HEX64_RE3 = /^[0-9a-f]{64}$/;
4191
+ var HEX64_RE4 = /^[0-9a-f]{64}$/;
3521
4192
  function assertHex64(value, what) {
3522
- if (!HEX64_RE3.test(value)) {
4193
+ if (!HEX64_RE4.test(value)) {
3523
4194
  throw new Error(
3524
4195
  `${what} must be a 64-char lowercase hex id (got ${JSON.stringify(value)})`
3525
4196
  );
@@ -3716,7 +4387,7 @@ async function runIssue(args, deps) {
3716
4387
  let bodyFile;
3717
4388
  let labels;
3718
4389
  try {
3719
- const { values } = parseArgs8({
4390
+ const { values } = parseArgs10({
3720
4391
  args: rest,
3721
4392
  options: {
3722
4393
  ...COMMON_OPTIONS2,
@@ -3812,7 +4483,7 @@ async function resolveCommentTarget(deps, targetEventId, relayUrl) {
3812
4483
  const rootEventId = firstTagValue(target.tags, "E");
3813
4484
  const rootKind = Number(firstTagValue(target.tags, "K"));
3814
4485
  const rootAuthor = firstTagValue(target.tags, "P");
3815
- if (rootEventId === void 0 || !HEX64_RE3.test(rootEventId) || !Number.isSafeInteger(rootKind) || rootAuthor === void 0 || !HEX64_RE3.test(rootAuthor)) {
4486
+ if (rootEventId === void 0 || !HEX64_RE4.test(rootEventId) || !Number.isSafeInteger(rootKind) || rootAuthor === void 0 || !HEX64_RE4.test(rootAuthor)) {
3816
4487
  throw new Error(
3817
4488
  `kind:1111 comment ${targetEventId} carries no usable NIP-22 root scope (E/K/P tags) \u2014 cannot derive the thread root to reply into`
3818
4489
  );
@@ -3836,7 +4507,7 @@ async function runComment(args, deps) {
3836
4507
  let targetEventId;
3837
4508
  let body;
3838
4509
  try {
3839
- const { values, positionals } = parseArgs8({
4510
+ const { values, positionals } = parseArgs10({
3840
4511
  args,
3841
4512
  options: {
3842
4513
  ...COMMON_OPTIONS2,
@@ -3917,6 +4588,8 @@ async function runPr(args, deps) {
3917
4588
  switch (sub) {
3918
4589
  case "create":
3919
4590
  return runPrCreate(rest, deps);
4591
+ case "merge":
4592
+ return runPrMerge(rest, deps);
3920
4593
  case "status":
3921
4594
  return runStatusCommand(rest, deps, PR_STATUS_SPEC);
3922
4595
  // FREE read subcommands (#278): relay queries only, no payment path.
@@ -3931,7 +4604,7 @@ async function runPr(args, deps) {
3931
4604
  return 0;
3932
4605
  default:
3933
4606
  io.err(
3934
- sub === void 0 ? "missing subcommand: rig pr <create|status|list|show>" : `unknown rig pr subcommand: ${sub}`
4607
+ sub === void 0 ? "missing subcommand: rig pr <create|merge|status|list|show>" : `unknown rig pr subcommand: ${sub}`
3935
4608
  );
3936
4609
  io.err(PR_USAGE);
3937
4610
  return 2;
@@ -3955,12 +4628,12 @@ async function resolveRevisedRoot(deps, rootId, relayUrl, addr) {
3955
4628
  `patch ${rootId} not found on ${relayUrl} \u2014 nothing was published or paid`
3956
4629
  );
3957
4630
  }
3958
- if (root.kind !== PATCH_KIND2) {
4631
+ if (root.kind !== PATCH_KIND3) {
3959
4632
  throw new Error(
3960
4633
  `event ${rootId} has kind ${root.kind}, not a kind:1617 patch \u2014 nothing was published or paid`
3961
4634
  );
3962
4635
  }
3963
- const aTag = `${REPOSITORY_ANNOUNCEMENT_KIND2}:${addr.ownerPubkey}:${addr.repoId}`;
4636
+ const aTag = `${REPOSITORY_ANNOUNCEMENT_KIND3}:${addr.ownerPubkey}:${addr.repoId}`;
3964
4637
  if (!root.tags.some((t) => t[0] === "a" && t[1] === aTag)) {
3965
4638
  throw new Error(
3966
4639
  `patch ${rootId} belongs to a different repository than ${aTag} \u2014 nothing was published or paid`
@@ -4011,7 +4684,7 @@ async function runPrCreate(rest, deps) {
4011
4684
  let bodyFile;
4012
4685
  let revises;
4013
4686
  try {
4014
- const { values } = parseArgs8({
4687
+ const { values } = parseArgs10({
4015
4688
  args: rest,
4016
4689
  options: {
4017
4690
  ...COMMON_OPTIONS2,
@@ -4145,7 +4818,7 @@ async function runPrCreate(rest, deps) {
4145
4818
  }
4146
4819
  var STATUS_KIND_BY_VALUE = {
4147
4820
  open: STATUS_OPEN_KIND2,
4148
- applied: STATUS_APPLIED_KIND2,
4821
+ applied: STATUS_APPLIED_KIND3,
4149
4822
  closed: STATUS_CLOSED_KIND2,
4150
4823
  draft: STATUS_DRAFT_KIND2
4151
4824
  };
@@ -4172,7 +4845,7 @@ async function runStatusCommand(args, deps, spec, fixedStatus) {
4172
4845
  let targetEventId;
4173
4846
  let status;
4174
4847
  try {
4175
- const { values, positionals } = parseArgs8({
4848
+ const { values, positionals } = parseArgs10({
4176
4849
  args,
4177
4850
  options: COMMON_OPTIONS2,
4178
4851
  allowPositionals: true
@@ -4258,8 +4931,8 @@ async function warnIfNotMaintainer(deps, args) {
4258
4931
  // src/cli/entry.ts
4259
4932
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
4260
4933
  import { homedir as homedir3 } from "os";
4261
- import { dirname as dirname4, join as join4 } from "path";
4262
- import { parseArgs as parseArgs9 } from "util";
4934
+ import { dirname as dirname4, join as join5 } from "path";
4935
+ import { parseArgs as parseArgs11 } from "util";
4263
4936
  var ENTRY_USAGE = `Usage: rig entry [<connector-url> | clear] [options]
4264
4937
 
4265
4938
  Name the TOON connector rig pays. A connector describes itself on GET /ilp
@@ -4283,8 +4956,8 @@ Options:
4283
4956
  --json machine-readable envelope
4284
4957
  -h, --help show this help`;
4285
4958
  function configPathFor2(env) {
4286
- const dir = env["TOON_CLIENT_HOME"] ?? join4(homedir3(), ".toon-client");
4287
- return join4(dir, "config.json");
4959
+ const dir = env["TOON_CLIENT_HOME"] ?? join5(homedir3(), ".toon-client");
4960
+ return join5(dir, "config.json");
4288
4961
  }
4289
4962
  function readEntryConfig(configPath) {
4290
4963
  try {
@@ -4329,7 +5002,7 @@ async function runEntry(args, deps) {
4329
5002
  let relayFlag;
4330
5003
  let json = false;
4331
5004
  try {
4332
- const parsed = parseArgs9({
5005
+ const parsed = parseArgs11({
4333
5006
  args,
4334
5007
  allowPositionals: true,
4335
5008
  options: {
@@ -4473,237 +5146,11 @@ async function runEntry(args, deps) {
4473
5146
  }
4474
5147
  }
4475
5148
 
4476
- // src/cli/fetch.ts
4477
- import { parseArgs as parseArgs10 } from "util";
4478
- var FETCH_USAGE = `Usage: rig fetch [remote] [options]
4479
-
4480
- Fetch from a TOON remote \u2014 FREE (relay reads + Arweave gateway downloads; no
4481
- payments, no identity needed). Reads the kind:30618 repository state from the
4482
- remote's relay, downloads only the git objects this repository is missing
4483
- (SHA-1 verified), and updates the remote-tracking refs
4484
- (refs/remotes/<remote>/*; tags land at refs/tags/*), reporting what moved.
4485
-
4486
- No merge happens: integrate with the git passthrough, e.g.
4487
- \`rig merge origin/main\`. \`rig fetch\` is the TOON transport and shadows
4488
- \`git fetch\` \u2014 plain-git fetches remain available via \`git fetch\` directly.
4489
-
4490
- The repo address (toon.repoid/toon.owner) comes from the config \`rig init\`
4491
- or \`rig clone\` writes; --repo-id/--owner override.
4492
-
4493
- Options:
4494
- --repo-id <id> repository id / NIP-34 d-tag (default: git config)
4495
- --owner <pubkey> repository owner (npub or 64-char hex; default: git config)
4496
- --relay <url> ad-hoc relay override \u2014 bypasses the remote's URL
4497
- --gateway <url> gateway to read objects through FIRST, on its raw-bytes
4498
- route <url>/raw/<txId>, ahead of the public gateway
4499
- list \u2014 name a private, local or air-gapped gateway to
4500
- fetch objects the public ones do not carry
4501
- (env RIG_ARWEAVE_GATEWAY also sets it)
4502
- --concurrency <n> parallel gateway downloads (default 8)
4503
- --json machine-readable result envelope
4504
- -h, --help show this help`;
4505
- var WS_URL_RE4 = /^wss?:\/\//i;
4506
- function localRefFor(refname, remote) {
4507
- if (refname.startsWith("refs/heads/")) {
4508
- return `refs/remotes/${remote}/${refname.slice("refs/heads/".length)}`;
4509
- }
4510
- if (refname.startsWith("refs/tags/")) return refname;
4511
- return null;
4512
- }
4513
- async function resolveLocalRef(repoRoot, refname) {
4514
- try {
4515
- const out = await runGit(repoRoot, [
4516
- "rev-parse",
4517
- "--verify",
4518
- "--quiet",
4519
- refname
4520
- ]);
4521
- const sha = out.trim();
4522
- return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
4523
- } catch {
4524
- return null;
4525
- }
4526
- }
4527
- async function runFetch(args, deps) {
4528
- const { io } = deps;
4529
- let json = false;
4530
- let remote = "origin";
4531
- let relayFlag;
4532
- let repoIdFlag;
4533
- let ownerFlag;
4534
- let gatewayFlag;
4535
- let concurrency;
4536
- try {
4537
- const { values, positionals } = parseArgs10({
4538
- args,
4539
- options: {
4540
- json: { type: "boolean", default: false },
4541
- relay: { type: "string" },
4542
- "repo-id": { type: "string" },
4543
- owner: { type: "string" },
4544
- gateway: { type: "string" },
4545
- concurrency: { type: "string" },
4546
- help: { type: "boolean", short: "h", default: false }
4547
- },
4548
- allowPositionals: true
4549
- });
4550
- if (values.help) {
4551
- io.out(FETCH_USAGE);
4552
- return 0;
4553
- }
4554
- json = values.json === true;
4555
- if (positionals.length > 1) {
4556
- throw new Error(
4557
- `expected at most one [remote] argument, got ${positionals.length}`
4558
- );
4559
- }
4560
- if (positionals[0] !== void 0) remote = positionals[0];
4561
- relayFlag = values.relay;
4562
- repoIdFlag = values["repo-id"];
4563
- ownerFlag = values.owner !== void 0 ? ownerToHex(values.owner) : void 0;
4564
- gatewayFlag = values.gateway;
4565
- if (values.concurrency !== void 0) {
4566
- concurrency = Number.parseInt(values.concurrency, 10);
4567
- if (!Number.isSafeInteger(concurrency) || concurrency < 1) {
4568
- throw new Error("--concurrency must be a positive integer");
4569
- }
4570
- }
4571
- } catch (err) {
4572
- io.err(err instanceof Error ? err.message : String(err));
4573
- io.err(FETCH_USAGE);
4574
- return 2;
4575
- }
4576
- try {
4577
- const repoRoot = await resolveRepoRoot(deps.cwd);
4578
- const toonConfig = await readToonConfig(repoRoot);
4579
- const repoId = repoIdFlag ?? toonConfig.repoId;
4580
- if (!repoId) throw new UnconfiguredRepoAddressError("repository id");
4581
- const owner = ownerFlag ?? toonConfig.owner;
4582
- if (!owner) throw new UnconfiguredRepoAddressError("repository owner");
4583
- let relayUrl;
4584
- if (relayFlag !== void 0) {
4585
- relayUrl = relayFlag;
4586
- } else {
4587
- const urls = await getGitRemoteUrls(repoRoot, remote);
4588
- if (urls.length === 0) throw new UnknownRemoteError(remote);
4589
- if (urls.length > 1) throw new MultiUrlRemoteError(remote, urls);
4590
- relayUrl = urls[0];
4591
- }
4592
- if (!WS_URL_RE4.test(relayUrl)) {
4593
- throw new InvalidRelayUrlError(
4594
- relayUrl,
4595
- `remote ${JSON.stringify(remote)}`
4596
- );
4597
- }
4598
- const remoteState = await fetchRemoteState({
4599
- relayUrls: [relayUrl],
4600
- ownerPubkey: owner,
4601
- repoId,
4602
- ...deps.webSocketFactory ? { webSocketFactory: deps.webSocketFactory } : {},
4603
- // The GraphQL fallback for SHAs the map does not cover asks the SAME
4604
- // permaweb the objects are read from (#183).
4605
- resolveSha: deps.resolveSha ?? shaResolverFor(gatewayFlag, deps.env)
4606
- });
4607
- const planned = [];
4608
- for (const [refname, sha] of remoteState.refs) {
4609
- if (!isSafeRefname(refname)) {
4610
- io.err(
4611
- `warning: skipping unsafe ref name from relay: ${JSON.stringify(refname)}`
4612
- );
4613
- continue;
4614
- }
4615
- const localRef = localRefFor(refname, remote);
4616
- if (localRef === null) {
4617
- io.err(
4618
- `warning: skipping ref outside refs/heads and refs/tags: ${refname}`
4619
- );
4620
- continue;
4621
- }
4622
- planned.push({ refname, localRef, newSha: sha });
4623
- }
4624
- const reader = new GitRepoReader(repoRoot);
4625
- const tips = [...new Set(planned.map((p) => p.newSha))];
4626
- const presentLocally = new Set(await reader.listAllObjectShas());
4627
- const collected = await collectRepoObjects({
4628
- tips,
4629
- shaToTxId: remoteState.shaToTxId,
4630
- resolveMissing: (shas) => remoteState.resolveMissing(shas),
4631
- presentLocally,
4632
- // `--gateway` / RIG_ARWEAVE_GATEWAY first, public list behind it (#176).
4633
- gateways: readGateways(gatewayFlag, deps.env),
4634
- ...deps.fetchFn ? { fetchFn: deps.fetchFn } : {},
4635
- ...concurrency !== void 0 ? { concurrency } : {}
4636
- });
4637
- if (collected.missing.length > 0) {
4638
- throw new MissingRemoteObjectsError(
4639
- collected.missing,
4640
- `cannot fetch from ${relayUrl}`
4641
- );
4642
- }
4643
- const written = await writeGitObjects(repoRoot, collected.objects.values());
4644
- const updates = [];
4645
- for (const { refname, localRef, newSha } of planned) {
4646
- const oldSha = await resolveLocalRef(repoRoot, localRef);
4647
- if (oldSha === newSha) {
4648
- updates.push({ refname, localRef, oldSha, newSha, kind: "up-to-date" });
4649
- continue;
4650
- }
4651
- let kind;
4652
- if (oldSha === null) {
4653
- kind = "new";
4654
- } else {
4655
- kind = await reader.isAncestor(oldSha, newSha) ? "fast-forward" : "forced";
4656
- }
4657
- await updateRef(repoRoot, localRef, newSha);
4658
- updates.push({ refname, localRef, oldSha, newSha, kind });
4659
- }
4660
- const moved = updates.filter((u) => u.kind !== "up-to-date");
4661
- if (json) {
4662
- io.emitJson({
4663
- command: "fetch",
4664
- repoAddr: { ownerPubkey: owner, repoId },
4665
- remote,
4666
- relay: relayUrl,
4667
- objectsDownloaded: written,
4668
- updates,
4669
- executed: true
4670
- });
4671
- return 0;
4672
- }
4673
- if (moved.length === 0) {
4674
- io.out("Already up to date.");
4675
- return 0;
4676
- }
4677
- io.out(`From ${relayUrl}`);
4678
- for (const u of moved) {
4679
- const short = (refname) => refname.replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/^refs\/remotes\//, "");
4680
- const src = short(u.refname);
4681
- const dst = short(u.localRef);
4682
- if (u.kind === "new") {
4683
- const label = u.refname.startsWith("refs/tags/") ? "[new tag]" : "[new branch]";
4684
- io.out(` * ${label.padEnd(17)} ${src.padEnd(14)} -> ${dst}`);
4685
- } else if (u.kind === "forced") {
4686
- io.out(
4687
- ` + ${u.oldSha.slice(0, 7)}...${u.newSha.slice(0, 7)} ${src.padEnd(14)} -> ${dst} (forced update)`
4688
- );
4689
- } else {
4690
- io.out(
4691
- ` ${u.oldSha.slice(0, 7)}..${u.newSha.slice(0, 7)} ${src.padEnd(14)} -> ${dst}`
4692
- );
4693
- }
4694
- }
4695
- io.out(`Downloaded ${written} object(s) (SHA-1 verified).`);
4696
- return 0;
4697
- } catch (err) {
4698
- return emitCliError(io, json, "fetch", err);
4699
- }
4700
- }
4701
-
4702
5149
  // src/cli/fund.ts
4703
5150
  import { readFileSync as readFileSync4 } from "fs";
4704
5151
  import { homedir as homedir4 } from "os";
4705
- import { join as join5 } from "path";
4706
- import { parseArgs as parseArgs11 } from "util";
5152
+ import { join as join6 } from "path";
5153
+ import { parseArgs as parseArgs12 } from "util";
4707
5154
  var DEVNET_FAUCET_URL = "https://faucet.devnet.toonprotocol.dev";
4708
5155
  var CHAINS = ["evm", "solana"];
4709
5156
  var CHAIN_ALIASES = {
@@ -4841,8 +5288,8 @@ function noFaucetGuidance(network, devnetOrigin) {
4841
5288
  return `${head}. If you meant the shared devnet, set TOON_CLIENT_NETWORK=devnet and re-run \`rig fund\` \u2014 no faucet URL is needed there. If this is a self-hosted network with its own faucet, set TOON_CLIENT_FAUCET_URL (or the faucetUrl config field). ${external}`;
4842
5289
  }
4843
5290
  function readFundConfig(env) {
4844
- const dir = env["TOON_CLIENT_HOME"] ?? join5(homedir4(), ".toon-client");
4845
- const configPath = join5(dir, "config.json");
5291
+ const dir = env["TOON_CLIENT_HOME"] ?? join6(homedir4(), ".toon-client");
5292
+ const configPath = join6(dir, "config.json");
4846
5293
  try {
4847
5294
  return {
4848
5295
  file: JSON.parse(readFileSync4(configPath, "utf8")),
@@ -4863,7 +5310,7 @@ async function runFund(args, deps) {
4863
5310
  let addressFlag;
4864
5311
  let json = false;
4865
5312
  try {
4866
- const { values, positionals } = parseArgs11({
5313
+ const { values, positionals } = parseArgs12({
4867
5314
  args,
4868
5315
  allowPositionals: true,
4869
5316
  options: {
@@ -5089,7 +5536,7 @@ var runGitPassthrough = (argv, options = {}) => {
5089
5536
  import { existsSync, mkdirSync as mkdirSync4 } from "fs";
5090
5537
  import { dirname as dirname5 } from "path";
5091
5538
  import { createInterface } from "readline/promises";
5092
- import { parseArgs as parseArgs12 } from "util";
5539
+ import { parseArgs as parseArgs13 } from "util";
5093
5540
  async function loadKeyOps() {
5094
5541
  const { generateKeystore, importKeystore } = await import("@toon-protocol/client");
5095
5542
  return { generateKeystore, importKeystore, deriveNostrKeyFromMnemonic };
@@ -5261,7 +5708,7 @@ async function runIdentity(args, deps) {
5261
5708
  }
5262
5709
  }
5263
5710
  function parseMintArgs(args, verb) {
5264
- const { values, positionals } = parseArgs12({
5711
+ const { values, positionals } = parseArgs13({
5265
5712
  args,
5266
5713
  options: {
5267
5714
  force: { type: "boolean", default: false },
@@ -5366,7 +5813,7 @@ async function runIdentityShow(args, deps) {
5366
5813
  let json = false;
5367
5814
  let help = false;
5368
5815
  try {
5369
- const parsed = parseArgs12({
5816
+ const parsed = parseArgs13({
5370
5817
  args,
5371
5818
  options: {
5372
5819
  json: { type: "boolean", default: false },
@@ -5474,14 +5921,14 @@ async function defaultReadSecretLine(prompt, isInteractive) {
5474
5921
  }
5475
5922
 
5476
5923
  // src/cli/inbox.ts
5477
- import { parseArgs as parseArgs13 } from "util";
5924
+ import { parseArgs as parseArgs14 } from "util";
5478
5925
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
5479
- import { join as join6 } from "path";
5926
+ import { join as join7 } from "path";
5480
5927
  import {
5481
5928
  ISSUE_KIND as ISSUE_KIND2,
5482
- PATCH_KIND as PATCH_KIND3,
5483
- REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND3,
5484
- STATUS_APPLIED_KIND as STATUS_APPLIED_KIND3,
5929
+ PATCH_KIND as PATCH_KIND4,
5930
+ REPOSITORY_ANNOUNCEMENT_KIND as REPOSITORY_ANNOUNCEMENT_KIND4,
5931
+ STATUS_APPLIED_KIND as STATUS_APPLIED_KIND4,
5485
5932
  STATUS_CLOSED_KIND as STATUS_CLOSED_KIND3,
5486
5933
  STATUS_DRAFT_KIND as STATUS_DRAFT_KIND3,
5487
5934
  STATUS_OPEN_KIND as STATUS_OPEN_KIND3
@@ -5599,7 +6046,7 @@ Options:
5599
6046
  -h, --help show this help`;
5600
6047
  var STATUS_KINDS2 = [
5601
6048
  STATUS_OPEN_KIND3,
5602
- STATUS_APPLIED_KIND3,
6049
+ STATUS_APPLIED_KIND4,
5603
6050
  STATUS_CLOSED_KIND3,
5604
6051
  STATUS_DRAFT_KIND3
5605
6052
  ];
@@ -5611,17 +6058,17 @@ var CI_KINDS = [
5611
6058
  CI_JOB_RESULT_KIND
5612
6059
  ];
5613
6060
  var INBOX_KINDS = [
5614
- PATCH_KIND3,
6061
+ PATCH_KIND4,
5615
6062
  ISSUE_KIND2,
5616
6063
  COMMENT_KIND,
5617
6064
  LEGACY_COMMENT_KIND,
5618
6065
  ...STATUS_KINDS2,
5619
6066
  ...CI_KINDS
5620
6067
  ];
5621
- var HEX64_RE4 = /^[0-9a-f]{64}$/;
6068
+ var HEX64_RE5 = /^[0-9a-f]{64}$/;
5622
6069
  var INBOX_CURSOR_FILENAME = "inbox-cursors.json";
5623
6070
  function cursorPath(env) {
5624
- return join6(clientStateDir(env), INBOX_CURSOR_FILENAME);
6071
+ return join7(clientStateDir(env), INBOX_CURSOR_FILENAME);
5625
6072
  }
5626
6073
  function readCursors(env) {
5627
6074
  try {
@@ -5660,7 +6107,7 @@ function hasTopic(event, topic) {
5660
6107
  return event.tags.some((t) => t[0] === "t" && t[1] === topic);
5661
6108
  }
5662
6109
  function typeOf(event) {
5663
- if (event.kind === PATCH_KIND3) {
6110
+ if (event.kind === PATCH_KIND4) {
5664
6111
  if (hasTopic(event, "root-revision")) return "revision";
5665
6112
  if (hasTopic(event, "root") || tagValue2(event.tags, "e") === void 0) {
5666
6113
  return "patch";
@@ -5696,7 +6143,7 @@ function toInboxEntry(event) {
5696
6143
  const type = typeOf(event);
5697
6144
  if (type === null) return null;
5698
6145
  const repo = event.tags.find(
5699
- (t) => t[0] === "a" && t[1]?.startsWith(`${REPOSITORY_ANNOUNCEMENT_KIND3}:`)
6146
+ (t) => t[0] === "a" && t[1]?.startsWith(`${REPOSITORY_ANNOUNCEMENT_KIND4}:`)
5700
6147
  )?.[1];
5701
6148
  return {
5702
6149
  id: event.id,
@@ -5722,7 +6169,7 @@ async function ownerAnnouncement(relays, owner, repoId, ws) {
5722
6169
  relays,
5723
6170
  [
5724
6171
  {
5725
- kinds: [REPOSITORY_ANNOUNCEMENT_KIND3],
6172
+ kinds: [REPOSITORY_ANNOUNCEMENT_KIND4],
5726
6173
  authors: [owner],
5727
6174
  "#d": [repoId]
5728
6175
  }
@@ -5731,7 +6178,7 @@ async function ownerAnnouncement(relays, owner, repoId, ws) {
5731
6178
  ).catch(() => /* @__PURE__ */ new Map());
5732
6179
  return newest(
5733
6180
  [...found.values()].filter(
5734
- (e) => e.kind === REPOSITORY_ANNOUNCEMENT_KIND3 && e.pubkey.toLowerCase() === owner && tagValue2(e.tags, "d") === repoId
6181
+ (e) => e.kind === REPOSITORY_ANNOUNCEMENT_KIND4 && e.pubkey.toLowerCase() === owner && tagValue2(e.tags, "d") === repoId
5735
6182
  )
5736
6183
  );
5737
6184
  }
@@ -5763,7 +6210,7 @@ async function runInbox(args, deps) {
5763
6210
  let remote;
5764
6211
  let relayFlags = [];
5765
6212
  try {
5766
- const { values, positionals } = parseArgs13({
6213
+ const { values, positionals } = parseArgs14({
5767
6214
  args,
5768
6215
  options: INBOX_OPTIONS,
5769
6216
  allowPositionals: true
@@ -5822,14 +6269,14 @@ async function runInbox(args, deps) {
5822
6269
  const announcements = await queryAll(
5823
6270
  configured,
5824
6271
  [
5825
- { kinds: [REPOSITORY_ANNOUNCEMENT_KIND3], authors: [me] },
5826
- { kinds: [REPOSITORY_ANNOUNCEMENT_KIND3], "#maintainers": [me] }
6272
+ { kinds: [REPOSITORY_ANNOUNCEMENT_KIND4], authors: [me] },
6273
+ { kinds: [REPOSITORY_ANNOUNCEMENT_KIND4], "#maintainers": [me] }
5827
6274
  ],
5828
6275
  ws
5829
6276
  );
5830
6277
  const byRepo = /* @__PURE__ */ new Map();
5831
6278
  for (const e of announcements.values()) {
5832
- if (e.kind !== REPOSITORY_ANNOUNCEMENT_KIND3) continue;
6279
+ if (e.kind !== REPOSITORY_ANNOUNCEMENT_KIND4) continue;
5833
6280
  const d = tagValue2(e.tags, "d");
5834
6281
  if (!d) continue;
5835
6282
  const key = `${e.pubkey.toLowerCase()}:${d}`;
@@ -5843,7 +6290,7 @@ async function runInbox(args, deps) {
5843
6290
  if (latest === null) continue;
5844
6291
  if (owner !== me && !parseMaintainers(latest.tags).includes(me)) continue;
5845
6292
  watched.push({
5846
- address: `${REPOSITORY_ANNOUNCEMENT_KIND3}:${owner}:${repoId}`,
6293
+ address: `${REPOSITORY_ANNOUNCEMENT_KIND4}:${owner}:${repoId}`,
5847
6294
  ownerPubkey: owner,
5848
6295
  authorized: authorizedAuthors(owner, latest.tags),
5849
6296
  relays: relaysTag(latest.tags)
@@ -5901,7 +6348,7 @@ async function runInbox(args, deps) {
5901
6348
  const unknownTargets = /* @__PURE__ */ new Set();
5902
6349
  for (const e of statusEvents) {
5903
6350
  const target = tagValue2(e.tags, "e");
5904
- if (!target || !HEX64_RE4.test(target)) continue;
6351
+ if (!target || !HEX64_RE5.test(target)) continue;
5905
6352
  const known = found.get(target);
5906
6353
  if (known) targetAuthors.set(target, known.pubkey.toLowerCase());
5907
6354
  else unknownTargets.add(target);
@@ -6035,7 +6482,7 @@ async function runInbox(args, deps) {
6035
6482
 
6036
6483
  // src/cli/init.ts
6037
6484
  import { basename as basename2 } from "path";
6038
- import { parseArgs as parseArgs14 } from "util";
6485
+ import { parseArgs as parseArgs15 } from "util";
6039
6486
 
6040
6487
  // src/cli/git-author.ts
6041
6488
  var PROFILE_KIND = 0;
@@ -6153,7 +6600,7 @@ Options:
6153
6600
  --json machine-readable report
6154
6601
  -h, --help show this help`;
6155
6602
  function parseInitArgs(args) {
6156
- const { values, positionals } = parseArgs14({
6603
+ const { values, positionals } = parseArgs15({
6157
6604
  args,
6158
6605
  options: {
6159
6606
  "repo-id": { type: "string" },
@@ -6380,8 +6827,8 @@ async function runInit(args, deps) {
6380
6827
  }
6381
6828
 
6382
6829
  // src/cli/maintainers.ts
6383
- import { parseArgs as parseArgs15 } from "util";
6384
- var HEX64_RE5 = /^[0-9a-f]{64}$/;
6830
+ import { parseArgs as parseArgs16 } from "util";
6831
+ var HEX64_RE6 = /^[0-9a-f]{64}$/;
6385
6832
  var REF_AUTHORITY_NOTICE = "Note: maintainers can move refs (publish honored repo state), not only set status.";
6386
6833
  var MAINTAINERS_USAGE = `Usage: rig maintainers <list|add|remove> [<pubkey>] [options]
6387
6834
 
@@ -6434,7 +6881,7 @@ async function runList2(args, deps) {
6434
6881
  const { io } = deps;
6435
6882
  let flags;
6436
6883
  try {
6437
- const { values, positionals } = parseArgs15({
6884
+ const { values, positionals } = parseArgs16({
6438
6885
  args,
6439
6886
  options: REPO_COMMAND_OPTIONS,
6440
6887
  allowPositionals: true
@@ -6501,7 +6948,7 @@ async function runMutate(op, args, deps) {
6501
6948
  let flags;
6502
6949
  let pubkey;
6503
6950
  try {
6504
- const { values, positionals } = parseArgs15({
6951
+ const { values, positionals } = parseArgs16({
6505
6952
  args,
6506
6953
  options: REPO_COMMAND_OPTIONS,
6507
6954
  allowPositionals: true
@@ -6515,7 +6962,7 @@ async function runMutate(op, args, deps) {
6515
6962
  throw new Error(`expected exactly one <pubkey> to ${op}`);
6516
6963
  }
6517
6964
  pubkey = ownerToHex(positionals[0]).toLowerCase();
6518
- if (!HEX64_RE5.test(pubkey)) {
6965
+ if (!HEX64_RE6.test(pubkey)) {
6519
6966
  throw new Error(
6520
6967
  `<pubkey> must resolve to 64-char hex (got ${JSON.stringify(positionals[0])})`
6521
6968
  );
@@ -6636,7 +7083,7 @@ async function runMutate(op, args, deps) {
6636
7083
  }
6637
7084
 
6638
7085
  // src/cli/refresh.ts
6639
- import { parseArgs as parseArgs16 } from "util";
7086
+ import { parseArgs as parseArgs17 } from "util";
6640
7087
  var REFRESH_USAGE = `Usage: rig refresh [options]
6641
7088
 
6642
7089
  Republish this repo's kind:30617 announcement with no field edit, refreshing
@@ -6672,7 +7119,7 @@ async function runRefresh(args, deps) {
6672
7119
  const { io } = deps;
6673
7120
  let flags;
6674
7121
  try {
6675
- const { values, positionals } = parseArgs16({
7122
+ const { values, positionals } = parseArgs17({
6676
7123
  args,
6677
7124
  options: REPO_COMMAND_OPTIONS,
6678
7125
  allowPositionals: true
@@ -6795,7 +7242,7 @@ async function runRefresh(args, deps) {
6795
7242
 
6796
7243
  // src/cli/name.ts
6797
7244
  import { randomUUID } from "crypto";
6798
- import { parseArgs as parseArgs17 } from "util";
7245
+ import { parseArgs as parseArgs18 } from "util";
6799
7246
  var ARIO_DECIMALS = 6;
6800
7247
  function renderMario(mario) {
6801
7248
  return `${mario.toString()} mARIO (~${formatUnits(mario.toString(), ARIO_DECIMALS)} ARIO)`;
@@ -7304,7 +7751,7 @@ async function resolveNameContext(deps, network, processId, mode) {
7304
7751
  return { identity, solanaAddress, network, processId, sdk, nostrSecretKey };
7305
7752
  }
7306
7753
  function parseNameFlags(args, env) {
7307
- const { values, positionals } = parseArgs17({
7754
+ const { values, positionals } = parseArgs18({
7308
7755
  args,
7309
7756
  allowPositionals: true,
7310
7757
  options: {
@@ -7863,7 +8310,7 @@ async function runName(args, deps) {
7863
8310
  }
7864
8311
 
7865
8312
  // src/cli/payout.ts
7866
- import { parseArgs as parseArgs18 } from "util";
8313
+ import { parseArgs as parseArgs19 } from "util";
7867
8314
  import { getAddress } from "viem";
7868
8315
  var PAYOUT_USAGE = `Usage: rig payout <set|clear|show> [<address>] [options]
7869
8316
 
@@ -7919,7 +8366,7 @@ async function runShow2(args, deps) {
7919
8366
  const { io } = deps;
7920
8367
  let flags;
7921
8368
  try {
7922
- const { values, positionals } = parseArgs18({
8369
+ const { values, positionals } = parseArgs19({
7923
8370
  args,
7924
8371
  options: REPO_COMMAND_OPTIONS,
7925
8372
  allowPositionals: true
@@ -7981,7 +8428,7 @@ async function runMutate2(op, args, deps) {
7981
8428
  let flags;
7982
8429
  let nextPayout = null;
7983
8430
  try {
7984
- const { values, positionals } = parseArgs18({
8431
+ const { values, positionals } = parseArgs19({
7985
8432
  args,
7986
8433
  options: REPO_COMMAND_OPTIONS,
7987
8434
  allowPositionals: true
@@ -8115,7 +8562,7 @@ async function runMutate2(op, args, deps) {
8115
8562
  }
8116
8563
 
8117
8564
  // src/cli/site.ts
8118
- import { parseArgs as parseArgs19 } from "util";
8565
+ import { parseArgs as parseArgs20 } from "util";
8119
8566
 
8120
8567
  // src/arweave-manifest.ts
8121
8568
  var DEFAULT_INDEX = "index.html";
@@ -8136,13 +8583,13 @@ function buildArweaveManifest(entries, indexPath = DEFAULT_INDEX, fallbackTxId)
8136
8583
  // src/cli/site-record.ts
8137
8584
  import { mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
8138
8585
  import { homedir as homedir5 } from "os";
8139
- import { join as join7 } from "path";
8586
+ import { join as join8 } from "path";
8140
8587
  var SITE_MANIFEST_FILENAME = "site-manifests.json";
8141
8588
  function storeDir2(env) {
8142
- return env["TOON_CLIENT_HOME"] ?? join7(homedir5(), ".toon-client");
8589
+ return env["TOON_CLIENT_HOME"] ?? join8(homedir5(), ".toon-client");
8143
8590
  }
8144
8591
  function storePath2(env) {
8145
- return join7(storeDir2(env), SITE_MANIFEST_FILENAME);
8592
+ return join8(storeDir2(env), SITE_MANIFEST_FILENAME);
8146
8593
  }
8147
8594
  function keyOf(repoId, ref) {
8148
8595
  return `${repoId}\0${ref}`;
@@ -8206,7 +8653,7 @@ Options (publish):
8206
8653
  estimate (nothing uploaded)
8207
8654
  -h, --help show this help`;
8208
8655
  function parseSiteArgs(args) {
8209
- const { values, positionals } = parseArgs19({
8656
+ const { values, positionals } = parseArgs20({
8210
8657
  args,
8211
8658
  options: {
8212
8659
  index: { type: "string" },
@@ -8616,6 +9063,8 @@ Commands rig owns:
8616
9063
  pr create publish a patch (kind:1617) with real
8617
9064
  \`git format-patch\` content (--revises <patch-id>
8618
9065
  publishes a revision of an existing patch)
9066
+ pr merge <patch-id> apply the latest revision with git am, push, then
9067
+ publish the applied status (owner/maintainer)
8619
9068
  pr status <event-id> <state> set an issue/patch status (kind:1630-1633):
8620
9069
  open | applied | closed | draft
8621
9070
  inbox everything new since you last read it (free):
@@ -8804,4 +9253,4 @@ export {
8804
9253
  rigVersion,
8805
9254
  dispatch
8806
9255
  };
8807
- //# sourceMappingURL=chunk-Y7TUE7JT.js.map
9256
+ //# sourceMappingURL=chunk-KQ4NQV7T.js.map