prreviewbuddy 0.70.2 → 0.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as MAX_WORKSPACE_PORT, $r as resolveAgent, A as relativeTime, B as readIndexToken, Dn as MANAGED_ROOT, F as runBatch, Fn as describeSubject, G as reviewsUrl, Gn as loadJob, In as findExistingReview, Jr as resolveTarget, Kr as WITHHELD_REASON, Mn as removeWorktree, Pn as describeMovement, Q as DEFAULT_WORKSPACE_PORT, Qn as clearClaim, Qr as git, R as queueForReview, Tn as modelHelpLines, U as ensureServer, V as bootstrapUrl, Vn as allJobs, X as workspaceUrl, Xn as progressSteps, Y as stopServer, Zn as purposeOf, _ as liveUpdateFor, _r as reviewedRepositories, _t as telemetryUploadConsent, a as wasBlocked, ai as STORE_ROOT, b as recordKissRun, bn as forgeResolver, bt as PACKAGE_NAME, ct as reanalyseReview, d as mergeUpdateInto, dr as mutateWorkspace, dt as append, ei as resolveModel, et as MIN_WORKSPACE_PORT, f as updateReview, fr as positionInLineage, g as UpdateAlreadyRunningError, gt as recordTelemetryUploadConsent, hr as recentWorkspaces, ht as deliver, i as liveJobsFor, ii as CONFIG_PATH, it as writePortPreference, j as batchIdentity, jn as readMarker, li as detectAgents, lr as loadWorkspace, mt as stamp, n as deleteReview$1, ni as readAgentPreference, oi as AGENT_IDS, ot as prepareReview, pt as record$1, qn as PHASES, qr as kissOutcome, ri as writeAgentPreference, rt as statedWorkspacePort, si as agentById, st as settleReview, tr as followedRefName, tt as parseWorkspacePort, ur as matchingWorkspaceIds, ut as startJob, v as runningJobs, vr as summarise, vt as telemetryUploadEnabled, yt as BUILD_VERSION } from "./delete_review-CRPRIRKg.js";
2
+ import { $ as MAX_WORKSPACE_PORT, A as relativeTime, B as readIndexToken, Dn as MANAGED_ROOT, F as runBatch, Fn as describeSubject, G as reviewsUrl, Gn as loadJob, In as findExistingReview, Jr as WITHHELD_REASON, Mn as removeWorktree, Pn as describeMovement, Q as DEFAULT_WORKSPACE_PORT, Qn as clearClaim, R as queueForReview, Tn as modelHelpLines, U as ensureServer, V as bootstrapUrl, Vn as allJobs, X as workspaceUrl, Xn as progressSteps, Xr as resolveTarget, Y as stopServer, Yr as kissOutcome, Zn as purposeOf, _ as liveUpdateFor, _r as reviewedRepositories, _t as telemetryUploadConsent, a as wasBlocked, ai as writeAgentPreference, b as recordKissRun, bn as forgeResolver, bt as PACKAGE_NAME, ci as AGENT_IDS, ct as reanalyseReview, d as mergeUpdateInto, di as detectAgents, dr as mutateWorkspace, dt as append, ei as git, et as MIN_WORKSPACE_PORT, f as updateReview, fr as positionInLineage, g as UpdateAlreadyRunningError, gt as recordTelemetryUploadConsent, hr as recentWorkspaces, ht as deliver, i as liveJobsFor, ii as readAgentPreference, it as writePortPreference, j as batchIdentity, jn as readMarker, li as agentById, lr as loadWorkspace, mt as stamp, n as deleteReview$1, ni as resolveModel, oi as CONFIG_PATH, ot as prepareReview, pt as record$1, qn as PHASES, rt as statedWorkspacePort, si as STORE_ROOT, st as settleReview, ti as resolveAgent, tr as followedRefName, tt as parseWorkspacePort, ur as matchingWorkspaceIds, ut as startJob, v as runningJobs, vr as summarise, vt as telemetryUploadEnabled, yt as BUILD_VERSION } from "./delete_review-BgIZpcsP.js";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
4
  import { spawn } from "node:child_process";
5
5
  import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
@@ -106,24 +106,35 @@ var AUDIENCES = {
106
106
  author: "writes the report to whoever wrote the code, as changes to make before submitting it",
107
107
  reviewer: "writes it for somebody reviewing somebody else's work, with whether each one is worth raising"
108
108
  };
109
+ function isCommandName(word) {
110
+ return word !== void 0 && Object.hasOwn(VALUED, word);
111
+ }
109
112
  function parse(argv) {
110
113
  if (argv.length === 0) return {
111
114
  name: "help",
112
115
  via: "bare"
113
116
  };
114
117
  const [head, ...rest] = argv;
115
- if (head === "--help" || head === "-h" || head === "help") return {
116
- name: "help",
117
- via: "asked"
118
- };
118
+ if (head === "--help" || head === "-h" || head === "help") {
119
+ const topic = rest[0];
120
+ return isCommandName(topic) ? {
121
+ name: "help",
122
+ via: "asked",
123
+ topic
124
+ } : {
125
+ name: "help",
126
+ via: "asked"
127
+ };
128
+ }
119
129
  if (head === "--version" || head === "-v") return { name: "version" };
120
- if (head === void 0 || !(head in VALUED)) return {
130
+ if (!isCommandName(head)) return {
121
131
  name: "error",
122
132
  message: unknownCommand(head)
123
133
  };
124
134
  if (rest.includes("--help") || rest.includes("-h")) return {
125
135
  name: "help",
126
- via: "asked"
136
+ via: "asked",
137
+ topic: head
127
138
  };
128
139
  const values = {};
129
140
  const flags = /* @__PURE__ */ new Set();
@@ -166,7 +177,7 @@ function parse(argv) {
166
177
  }
167
178
  return {
168
179
  name: "error",
169
- message: `\`${head}\` does not take ${name}. Run \`prreviewbuddy --help\` to see what it takes.`
180
+ message: `\`${head}\` does not take ${name}. Run \`prreviewbuddy ${head} --help\` to see what it takes.`
170
181
  };
171
182
  }
172
183
  if (head === "review" && positional[0]) {
@@ -240,7 +251,7 @@ function parse(argv) {
240
251
  const [action, key, value] = positional;
241
252
  if (action !== "get" && action !== "set" && action !== "path") return {
242
253
  name: "error",
243
- message: "`config` takes `get`, `set` or `path`. Run `prreviewbuddy --help` for what it can read and set."
254
+ message: "`config` takes `get`, `set` or `path`. Run `prreviewbuddy config --help` for what it can read and set."
244
255
  };
245
256
  if (action === "path") return {
246
257
  name: "config",
@@ -759,16 +770,6 @@ function orList(items) {
759
770
  }
760
771
  var AGENT_NAMES = orList([...AGENT_IDS].sort());
761
772
  /**
762
- * Where model names come from, laid out from what each adapter says about its own tool.
763
- *
764
- * Built from the registry for the same reason `AGENT_NAMES` is, and one step further: this file
765
- * names neither the agents nor the way each is asked. An adapter that learns a better answer
766
- * changes it in one place, and a fourth adapter appears here without this string being touched.
767
- *
768
- * No model is named anywhere in it, deliberately. Which models exist belongs to the vendor, and a
769
- * copy of it here would be wrong by the next release.
770
- */
771
- /**
772
773
  * The adapters, skipping any this build cannot produce.
773
774
  *
774
775
  * Guarded for the reason `review_job.ts` guards its own registry lookups: an id the registry cannot
@@ -785,139 +786,188 @@ function knownAgents() {
785
786
  }
786
787
  });
787
788
  }
788
- var HELP = `PR Review Buddy reviews a branch in an isolated checkout and opens the result
789
- in your browser. The review runs in a separate process against a worktree pinned to one commit, so
790
- your own checkout is never read or written while it works.
791
-
792
- prreviewbuddy review review the current branch
793
- prreviewbuddy review --branch <branch> review another branch, without checking it out
794
- prreviewbuddy review --commit <commit> review the change one commit made, against its parent
795
- prreviewbuddy review --pr <url> review a pull request
796
- prreviewbuddy review --pr <url> <url> ...
797
- review several pull requests, each on its own, two at a
798
- time; --concurrency <n> changes how many
799
- prreviewbuddy review ... --queue also put each review on your review queue, as soon as
800
- it exists rather than when it is ready
801
- prreviewbuddy review --base <ref> compare against a base of your choosing
802
- prreviewbuddy review --agent <agent> review with ${AGENT_NAMES}
803
- prreviewbuddy review --model <model> ask that agent for a particular model. Reviews keep
804
- their requested model when reanalysed; use
805
- --reanalyse --model <model> to change it.${((rows) => {
789
+ /**
790
+ * Where model names come from, laid out from what each adapter says about its own tool, under
791
+ * `--model` in `review --help` at the column it is given.
792
+ *
793
+ * Built from the registry for the same reason `AGENT_NAMES` is, and one step further: this file
794
+ * names neither the agents nor the way each is asked. An adapter that learns a better answer
795
+ * changes it in one place, and a fourth adapter appears here without this string being touched.
796
+ *
797
+ * No model is named anywhere in it, deliberately. Which models exist belongs to the vendor, and a
798
+ * copy of it here would be wrong by the next release.
799
+ *
800
+ * Measured rather than guessed: a hardcoded column would go ragged the day an adapter with a longer
801
+ * display name is registered, and nothing would fail to say so. The lead-in belongs to the table
802
+ * rather than to the flag, so an empty table takes its promise with it. "To find the names:"
803
+ * followed by nothing would be worse than saying nothing at all.
804
+ *
805
+ * The flag's own sentence deliberately does not say what happens without it. It used to read
806
+ * "rather than whichever one it uses by default", which is a claim about the no-flag case and is
807
+ * false once a review is pinned: re-analysing one asks for the pin, not the agent's default.
808
+ */
809
+ function modelHelp(indent) {
810
+ const rows = modelHelpLines(knownAgents());
806
811
  if (rows.length === 0) return "";
807
812
  const width = Math.max(...rows.map(([name]) => name.length));
808
- const table = rows.map(([name, how]) => `${" ".repeat(44)}${name.padEnd(width + 2)}${how}`).join("\n");
809
- return `\n${" ".repeat(42)}To find the names:\n${table}`;
810
- })(modelHelpLines(knownAgents()))}
811
-
812
- prreviewbuddy review --lens <name> run a specialised review lens: ${orList([...LENS_NAMES])}
813
- prreviewbuddy review --lens kiss --audience author
814
- ask whether the change is more complicated than it needs
815
- to be, written for whoever wrote it
816
- prreviewbuddy review --lens kiss --audience reviewer
817
- the same question, written for reviewing somebody else's
818
- work
819
-
820
- prreviewbuddy review --update bring the review of that target up to date
821
- prreviewbuddy review --reanalyse analyse the same commit again, for a fresh judgement
822
- prreviewbuddy review --fresh review the target again, keeping the existing review
823
- prreviewbuddy review --review <review> --update
824
- act on one review by its review ID
825
- prreviewbuddy review --review <review> --delete
826
- delete one review and its isolated checkouts
813
+ const table = rows.map(([name, how]) => `${" ".repeat(indent + 2)}${name.padEnd(width + 2)}${how}`).join("\n");
814
+ return `\n${" ".repeat(indent)}To find the names:\n${table}`;
815
+ }
816
+ /**
817
+ * The lenses, named in the help from the registry that defines them.
818
+ *
819
+ * Built rather than written down for the same reason `AGENT_NAMES` is: a hand-written list is copy
820
+ * that goes quietly wrong the day a second lens is registered, and the help is the one place
821
+ * somebody looks to find out what `--lens` takes.
822
+ */
823
+ var LENS_LIST = orList([...LENS_NAMES]);
824
+ /**
825
+ * The help, at four levels:
826
+ *
827
+ * - `ORIENTATION`, for `prreviewbuddy` on its own: what this is and what to type next.
828
+ * - `HELP`, for `prreviewbuddy help` and `--help`: every command, one line each.
829
+ * - `COMMAND_HELP`, for `prreviewbuddy <command> --help`: that command's syntax and flags.
830
+ * - Help in the workspace (`help_page.ts`): what a review covers, and what its parts mean.
831
+ */
832
+ var ORIENTATION = `PR Review Buddy
833
+ Understand before you approve.
827
834
 
828
- prreviewbuddy open list your reviews and open the index
829
- prreviewbuddy open <review> open a review by its review ID
835
+ Review code changes with ${orList(knownAgents().map((agent) => agent.displayName))} in an isolated checkout,
836
+ then explore the review in your browser.
830
837
 
831
- prreviewbuddy agents which coding agents you have
832
- prreviewbuddy agents <agent> show details for ${AGENT_NAMES}
833
- prreviewbuddy config get agent the coding agent used when you do not name one
834
- prreviewbuddy config set agent <agent> remember ${AGENT_NAMES}
835
- prreviewbuddy config get telemetry-upload
836
- whether usage telemetry is sent. On by default
837
- prreviewbuddy config set telemetry-upload on|off
838
- send it, or stop
839
- prreviewbuddy config get port the port the workspace runs on
840
- prreviewbuddy config set port <port> move it, from the next start onwards
841
- prreviewbuddy config path where these settings are kept, to edit by hand
838
+ prreviewbuddy review Review this branch
839
+ prreviewbuddy review --pr <url> Review a pull request
840
+ prreviewbuddy open Open previous reviews
842
841
 
843
- prreviewbuddy uninstall remove everything this put on your machine
844
- prreviewbuddy uninstall --keep-reviews keep your reviews and settings, clear the rest
842
+ More: prreviewbuddy help`;
843
+ /** Where the concepts are explained, said the same way wherever the CLI points at it. */
844
+ var WORKSPACE_HELP = "Help in the workspace (open it with `prreviewbuddy open`, then choose Help)";
845
+ var HELP = `PR Review Buddy
846
+ Understand before you approve.
845
847
 
846
- Anything in the first group says what to review. Anything in the second says what to do to it, and
847
- they go together: \`prreviewbuddy review --branch feat/foo --update\` brings the review of feat/foo up
848
- to date without checking it out. \`prreviewbuddy open\` prints a review ID beside each review, and
849
- you need one to tell two reviews of the same branch apart or to delete one. Deleting a review
850
- removes its record and the checkouts it was made in, and never touches your branch or its commits.
848
+ Usage: prreviewbuddy <command> [options]
851
849
 
852
- A review lens asks a specialised question of the same change instead of the standard review's.
853
- \`--lens kiss\` asks not whether the change is correct, but whether the complexity it introduces is
854
- justified, or whether the same requirements could be met with less machinery. A lens runs beside
855
- the standard review in the same workspace rather than replacing it, and it does not need one to
856
- have been made first. \`--audience\` is required with \`--lens kiss\` and is never guessed from what
857
- you are reviewing, because a reviewer checks out somebody else's branch and an author reviews their
858
- own pull request.
850
+ Commands
851
+ prreviewbuddy review review this branch, another branch, a commit or pull requests
852
+ prreviewbuddy open list your reviews and open the workspace in your browser
853
+ prreviewbuddy agents which coding agents you have
854
+ prreviewbuddy config the default agent, the workspace port and usage telemetry
855
+ prreviewbuddy uninstall remove everything PR Review Buddy put on your machine
859
856
 
860
- Several pull requests at once are several ordinary reviews, each with its own link, and the command
861
- prints them all when it ends. One that fails does not stop the others. Ctrl-C stops them all, and
862
- running the same command again carries each one on from where it got to.
857
+ Common examples
858
+ prreviewbuddy review review the branch you have checked out
859
+ prreviewbuddy review --pr <url> review a pull request
860
+ prreviewbuddy review --update bring that review up to date with new commits
861
+ prreviewbuddy open <review> open one review by its review ID
863
862
 
864
- Reviews can also be deleted from the list in your browser, one at a time or a whole branch at once.
863
+ More
864
+ prreviewbuddy <command> --help that command's options, such as \`review --help\`
865
+ prreviewbuddy --version the version you have
866
+ Help in the workspace what a review covers, updating and reanalysing, lenses, and
867
+ how long reviews are kept. Run \`prreviewbuddy open\`, then
868
+ choose Help`;
869
+ var REVIEW_HELP = `prreviewbuddy review: review a change in an isolated checkout and open it in your browser.
865
870
 
866
- What gets reviewed
871
+ Usage: prreviewbuddy review [what to review] [what to do to it] [options]
867
872
 
868
- A review is the combined change between a base and the branch you review, as one diff. It is not
869
- just the latest commit. The base determines the split point (git's merge-base of the base and your
870
- branch), and PR Review Buddy reviews the changes on your branch since that point.
873
+ What to review. Leave it out for the branch you have checked out.
874
+ --branch <branch> another branch, local or remote, without checking it out.
875
+ origin/feat/foo reviews what is on the remote
876
+ --commit <commit> the change one commit made, against its parent
877
+ --pr <url> a pull request
878
+ --pr <url> <url> ... several pull requests, each its own review
879
+ --review <review> one existing review, by its review ID. \`prreviewbuddy open\`
880
+ prints a review ID beside each review
871
881
 
872
- main: A---B---C
873
- \\
874
- feature: D---E
882
+ What to do to it. Leave it out to start a review, or to find the one that exists.
883
+ --update bring the review up to date with new commits
884
+ --reanalyse analyse the same commit again, for a fresh judgement
885
+ --fresh review the target again, keeping the existing review
886
+ --delete delete the review and its isolated checkouts, never your branch.
887
+ Asks first; --yes answers for you
875
888
 
876
- prreviewbuddy review --base main reviews D and E together
889
+ Options
890
+ --base <ref> compare against this base instead of the default branch. When
891
+ your local and remote copies of it differ, you are asked which
892
+ --agent <agent> review with ${AGENT_NAMES}
893
+ --model <model> ask that agent for a particular model. Reviews keep their
894
+ requested model when reanalysed; use --reanalyse --model <model>
895
+ to change it.${modelHelp(30)}
896
+ --lens <name> run a specialised review lens: ${LENS_LIST}
897
+ --audience <audience> who the lens writes for: author (whoever wrote the change) or
898
+ reviewer (somebody reviewing it). Required with --lens kiss
899
+ --concurrency <n> with several --pr URLs, how many are reviewed at once. Default 2
900
+ --queue put each review on your review queue as soon as it exists
877
901
 
878
- C is on main but not on your branch, so it is not part of the review, and the review does not show
879
- its changes as removed. Commits already in the base are never reviewed again.
902
+ A target and an operation go together:
903
+ prreviewbuddy review --branch feat/foo --update
904
+ prreviewbuddy review --base origin/main
905
+ prreviewbuddy review --pr <url> <url> --queue
906
+ prreviewbuddy review --lens kiss --audience author
907
+ prreviewbuddy review --review <review> --delete
880
908
 
881
- When your local main and origin/main are different commits, which one you name moves the split
882
- point:
909
+ What a review covers, and how updating, reanalysing and lenses work, is in
910
+ ${WORKSPACE_HELP}.`;
911
+ var OPEN_HELP = `prreviewbuddy open: list your reviews and open the workspace in your browser.
883
912
 
884
- origin/main: A---B
885
- \\
886
- local main: C---D
887
- \\
888
- feature: E
913
+ Usage
914
+ prreviewbuddy open list your reviews, each with its review ID, and open the list
915
+ prreviewbuddy open <review> open one review by its review ID
889
916
 
890
- --base refs/heads/main reviews E
891
- --base origin/main reviews C, D and E together
917
+ The workspace starts if it is not running. How long reviews are kept, and how to stop or move the
918
+ workspace, is in ${WORKSPACE_HELP}.`;
919
+ /**
920
+ * What each adapter says about setting up its own tool, under its name. From the registry, as the
921
+ * model table is, so this file names no agent's configuration. Empty when no adapter has a note.
922
+ */
923
+ function agentSetupNotes() {
924
+ return knownAgents().filter((agent) => agent.setupNotes?.length).map((agent) => `\n\n${agent.displayName}\n${(agent.setupNotes ?? []).map((line) => ` ${line}`).join("\n")}`).join("");
925
+ }
926
+ /** Each command's own help, for `prreviewbuddy <command> --help` and `prreviewbuddy help <command>`. */
927
+ var COMMAND_HELP = {
928
+ review: REVIEW_HELP,
929
+ open: OPEN_HELP,
930
+ agents: `prreviewbuddy agents: the coding agents PR Review Buddy can review with.
892
931
 
893
- Without --base, the repository's default branch is the base. If its local and remote copies are
894
- different commits, PR Review Buddy asks which one you mean and says what each would review.
895
- Uncommitted changes are never included: a review is a fixed snapshot of your commits.
932
+ Usage
933
+ prreviewbuddy agents which coding agents you have, and which one is used by default
934
+ prreviewbuddy agents <agent> show details for ${AGENT_NAMES}
896
935
 
897
- Common examples
936
+ Choose the default with \`prreviewbuddy config set agent <agent>\`, or one review's agent with
937
+ \`prreviewbuddy review --agent <agent>\`.
898
938
 
899
- prreviewbuddy review --base refs/heads/main
900
- everything on this branch since it left your local main
901
- prreviewbuddy review --base origin/main
902
- everything on this branch not yet on origin/main
903
- prreviewbuddy review --commit <commit> one commit, against its parent
939
+ Each agent uses its own installation and its existing authentication.${agentSetupNotes()}`,
940
+ config: `prreviewbuddy config: read and change your settings.
904
941
 
905
- There is no account and no API key. PR Review Buddy uses a coding agent installed on your machine
906
- and that agent's existing authentication, and nothing here ever asks you for a credential.
942
+ Usage
943
+ prreviewbuddy config get agent the coding agent used when you do not name one
944
+ prreviewbuddy config set agent <agent> remember ${AGENT_NAMES}
945
+ prreviewbuddy config get telemetry-upload
946
+ whether usage telemetry is sent. On by default
947
+ prreviewbuddy config set telemetry-upload on|off
948
+ send it, or stop
949
+ prreviewbuddy config get port the port the workspace runs on. ${DEFAULT_WORKSPACE_PORT} by default
950
+ prreviewbuddy config set port <port> move it, from the next time the workspace starts
951
+ prreviewbuddy config path where these settings are kept, to edit by hand
907
952
 
908
- Your workspace is at http://localhost:${DEFAULT_WORKSPACE_PORT} and each review has an address
909
- under it, so a link to one is worth keeping and still opens tomorrow. Move it with
910
- \`prreviewbuddy config set port\`, or from Settings in the workspace itself, and the new port is used
911
- the next time the workspace starts. If something else is already on that port, PR Review Buddy says
912
- so rather than quietly moving somewhere you have not bookmarked.
953
+ The port can also be changed from Settings in the workspace.`,
954
+ uninstall: `prreviewbuddy uninstall: remove everything PR Review Buddy put on your machine.
913
955
 
914
- Reviews are kept in ~/.prreviewbuddy for thirty days. The workspace server outlives this command,
915
- so a review stays open after the terminal that started it has closed. There is no command to stop
916
- it, on purpose: open any review and use "Stop server" in the left rail. One server serves all of
917
- them, and the page says so before it asks.
956
+ Usage
957
+ prreviewbuddy uninstall remove your reviews, settings and isolated checkouts,
958
+ stop the workspace, and clean up the git bookkeeping
959
+ left in the repositories it reviewed
960
+ prreviewbuddy uninstall --keep-reviews keep your reviews and settings, clear the rest
918
961
 
919
- The isolated checkout a review was made in is kept for six hours after it finishes, because that is
920
- what the assistant reads when you ask it questions, and is then removed along with the rest.`;
962
+ Options
963
+ --yes do not ask for confirmation first
964
+ --force stop a review that is still being made, rather than refusing over it`
965
+ };
966
+ /** What a `help` command prints. */
967
+ function helpFor(command) {
968
+ if (command.via === "bare") return ORIENTATION;
969
+ return command.topic ? COMMAND_HELP[command.topic] : HELP;
970
+ }
921
971
  /**
922
972
  * An agent asked for by name that this build does not have.
923
973
  *
@@ -1610,7 +1660,7 @@ function firstRun(version) {
1610
1660
  `PR Review Buddy ${version}`,
1611
1661
  "",
1612
1662
  " prreviewbuddy agents which coding agents you have",
1613
- " prreviewbuddy --help everything it does",
1663
+ " prreviewbuddy help every command",
1614
1664
  ""
1615
1665
  ].join("\n");
1616
1666
  }
@@ -1770,6 +1820,20 @@ function out(text) {
1770
1820
  function err(text) {
1771
1821
  process.stderr.write(`${text}\n`);
1772
1822
  }
1823
+ //#endregion
1824
+ //#region src/commands/review_batch.ts
1825
+ /**
1826
+ * `prreviewbuddy review --pr <url> <url> ...`: several ordinary reviews, started together.
1827
+ *
1828
+ * Orchestration only. Each pull request is resolved, looked up, started and run through exactly
1829
+ * the functions a single `--pr` uses (`prepareReview`, `settleReview`), and ends as an ordinary
1830
+ * review with its own workspace, job and link. There is no batch record and nothing is compared
1831
+ * across pull requests. What this adds is the scheduling, one screen describing all of them, a
1832
+ * summary at the end, and Ctrl-C.
1833
+ *
1834
+ * The harness calls arrive as `BatchDeps` so the glue is testable without mocking the harness
1835
+ * module by module; `realDeps` is the only place they are wired to the real thing.
1836
+ */
1773
1837
  /**
1774
1838
  * What to call each pull request on screen: `#128`, or `!45` for a merge request. Two from
1775
1839
  * different repositories with one number are given the repository's name too.
@@ -3346,7 +3410,7 @@ async function main(argv) {
3346
3410
  async function run(command) {
3347
3411
  switch (command.name) {
3348
3412
  case "help":
3349
- out(HELP);
3413
+ out(helpFor(command));
3350
3414
  return 0;
3351
3415
  case "version":
3352
3416
  out(BUILD_VERSION);