prreviewbuddy 0.46.0 → 0.48.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.48.0
4
+
5
+ **Active, Waiting and Done.** A review can now be marked **Waiting**, for when you have done your
6
+ pass and expect another round, or **Done**, for when you are finished with it. The reviews list keeps
7
+ your active reviews at the top, with **Waiting** below them and **Done** below that, folded away. Use
8
+ the **⋯** menu on a card, or select several and use the bar at the bottom. **Move to active** puts a
9
+ review back. This is separate from **Reviewed**, which still records that you have been through it.
10
+
11
+ **Waiting reviews come back when something changes.** If a Waiting review gets new commits, or its
12
+ pull request is merged, closed or reopened, it shows up in the main list again marked **Changed while
13
+ waiting**. Marking it Waiting again puts it back. A Done review never comes back by itself; if it
14
+ changes, it is marked **Changed since done** where it is. Marking a review Waiting starts watching
15
+ it straight away, so a push made soon after still brings it back. Adding a Waiting or Done review to
16
+ your review queue moves it back to Active.
17
+
18
+ **The list no longer reorders when you open a review.** Reviews are ordered by what last happened to
19
+ the change: when it was analysed, when new commits arrived, or when the pull request was merged,
20
+ closed or reopened. The time on each card now says which of those it was, for example "Updated
21
+ 2 hours ago" or "Merged 1 day ago". Saved reviews still come first.
22
+
23
+ **Load more instead of pages.** Each section shows fifteen reviews and a **Load more** button for the
24
+ rest. Search and the filters still cover every review, in all three sections.
25
+
26
+ **Done reviews are kept longer.** Like saved reviews, Done reviews are kept for ninety days rather
27
+ than thirty, counting from the last time you opened or marked them.
28
+
29
+ **Light mode.** The workspace now has a light theme as well as the dark one. The rail, the top bars,
30
+ Buddy AI, the reviews list, Notifications and Settings are drawn in pale greys around a white
31
+ review, so the review stays the brightest thing on the screen. Purple is kept for what you have
32
+ chosen and for the main action, as a pale tint rather than a solid block.
33
+
34
+ **Follows your device, or stays put.** Settings has a new **Appearance** section with **System**,
35
+ **Light** and **Dark**. System is the default, and it changes with your device at once, without
36
+ reloading the page, when your Mac switches between light and dark. Choosing a theme shows it on the
37
+ Settings page straight away; **Save changes** keeps it. If you have not chosen, the workspace follows
38
+ your device, so on a Mac set to light it now opens in light mode.
39
+
40
+ **Readable in both.** Every piece of text in the light theme, including timestamps, counts and other
41
+ small details, meets the WCAG 4.5:1 contrast level against whatever it sits on.
42
+
43
+ **Fixed: buttons in a review that went blank on hover.** In the dark theme, pointing at **Open in**
44
+ your editor, **Show more of this file**, **View files**, **Regenerate** or a diagram's zoom buttons
45
+ turned the label white on the white review, so it disappeared. They now keep their dark label.
46
+
47
+ **A clearer message when OpenAI refuses Codex while it is signed in.** If Codex says it is signed in
48
+ but OpenAI answers "Incorrect API key", the review no longer suggests signing in again, and no longer
49
+ suggests looking for an API key of your own: the key in that error is Codex's own. It now suggests
50
+ `codex doctor` to see what Codex is using, and `codex features list` to find an experimental Codex
51
+ feature to turn off, which is what fixed it when we saw it.
52
+
3
53
  ## 0.46.0
4
54
 
5
55
  **The change map: see what a change is about, and how its parts affect each other.** The Diagrams
@@ -1129,6 +1129,19 @@ var CodexUnavailableError = class extends AgentUnavailableError {};
1129
1129
  */
1130
1130
  var AUTHENTICATION = /not (?:logged|signed) in|unauthori[sz]ed|401|authenticat|credential|sign[- ]?in|log ?in/i;
1131
1131
  /**
1132
+ * OpenAI refusing a request Codex believes is signed in, which is not nobody being signed in.
1133
+ *
1134
+ * Seen with Codex reporting "Logged in using ChatGPT" and no API key anywhere in the reviewer's
1135
+ * environment: the key named in the error is Codex's own, not one of theirs. Signing in again did
1136
+ * not clear it; turning off an experimental Codex feature did. So the advice is Codex's own
1137
+ * diagnosis and its feature switches, never a login loop and never a hunt for an API key. Still an
1138
+ * authentication failure, so no Retry is offered.
1139
+ */
1140
+ var REJECTED_KEY = /incorrect api key|invalid[_ ]api[_ ]key/i;
1141
+ function isAuthentication(detail) {
1142
+ return AUTHENTICATION.test(detail) || REJECTED_KEY.test(detail);
1143
+ }
1144
+ /**
1132
1145
  * Which kind of failure the agent's own sentence describes.
1133
1146
  *
1134
1147
  * Only the one distinction that changes what a person is offered: a run that failed because nobody
@@ -1137,7 +1150,7 @@ var AUTHENTICATION = /not (?:logged|signed) in|unauthori[sz]ed|401|authenticat|c
1137
1150
  * label for them.
1138
1151
  */
1139
1152
  function kindOf(detail) {
1140
- return AUTHENTICATION.test(detail) ? "agent_authentication_failed" : "agent_execution_failed";
1153
+ return isAuthentication(detail) ? "agent_authentication_failed" : "agent_execution_failed";
1141
1154
  }
1142
1155
  var codexAgent = {
1143
1156
  id: CODEX_AGENT_ID,
@@ -1147,8 +1160,10 @@ var codexAgent = {
1147
1160
  captureEnv: captureEnv$1,
1148
1161
  /** Which tool, which profile, and the one command that changes it. See `agent.ts` for the budget. */
1149
1162
  explainFailure(detail, env = {}) {
1150
- if (!AUTHENTICATION.test(detail)) return null;
1151
- return `Codex could not sign in. This review was started using ${env.CODEX_HOME ? `the Codex profile at \`${env.CODEX_HOME}\`` : "your default Codex profile"}, so run \`codex login\` against that one.`;
1163
+ if (!isAuthentication(detail)) return null;
1164
+ const profile = env.CODEX_HOME ? `the Codex profile at \`${env.CODEX_HOME}\`` : "your default Codex profile";
1165
+ if (REJECTED_KEY.test(detail)) return `OpenAI refused a request from ${profile} even though Codex reports being signed in, which usually points to Codex's own setup rather than your sign-in. Run \`codex doctor\` to see what it is using, and check \`codex features list\` for an experimental feature to turn off with \`codex features disable <name>\`.`;
1166
+ return `Codex could not sign in. This review was started using ${profile}, so run \`codex login\` against that one.`;
1152
1167
  },
1153
1168
  /**
1154
1169
  * Whether the command is here and runs. Deliberately not whether it is signed in.
@@ -4112,6 +4127,95 @@ function normalise(ids) {
4112
4127
  return seen;
4113
4128
  }
4114
4129
  //#endregion
4130
+ //#region ../../packages/review-harness/src/workspace/lifecycle.ts
4131
+ /**
4132
+ * What happens next with a change, as the reviewer says it: still in play, parked until something
4133
+ * moves, or finished with.
4134
+ *
4135
+ * A separate axis from New / In progress / Reviewed, which says what the reviewer has *done*. A
4136
+ * change can be reviewed and waiting for another push, or reviewed and done, and one field cannot
4137
+ * hold both answers.
4138
+ *
4139
+ * One registry that the stored type, the card, the menus, the bulk bar and the route all derive
4140
+ * from. Pure on purpose: the reviews page's script imports it to move a card between sections after
4141
+ * a mark, without asking the server for the page again.
4142
+ */
4143
+ var LIFECYCLES = [
4144
+ {
4145
+ id: "active",
4146
+ action: "Move to active"
4147
+ },
4148
+ {
4149
+ id: "waiting",
4150
+ action: "Mark waiting"
4151
+ },
4152
+ {
4153
+ id: "done",
4154
+ action: "Mark done"
4155
+ }
4156
+ ];
4157
+ function isLifecycle(value) {
4158
+ return LIFECYCLES.some((lifecycle) => lifecycle.id === value);
4159
+ }
4160
+ /** A stored value read defensively: anything this code did not write reads as Active. */
4161
+ function parseLifecycle(raw) {
4162
+ if (typeof raw !== "object" || raw === null) return void 0;
4163
+ const { state, at } = raw;
4164
+ if (state !== "waiting" && state !== "done" || typeof at !== "number" || !Number.isFinite(at)) return void 0;
4165
+ return {
4166
+ state,
4167
+ at
4168
+ };
4169
+ }
4170
+ function lifecycleAction(lifecycle) {
4171
+ return LIFECYCLES.find((entry) => entry.id === lifecycle).action;
4172
+ }
4173
+ var ACTIVITY_LABELS = {
4174
+ created: "Created",
4175
+ updated: "Updated",
4176
+ merged: "Merged",
4177
+ closed: "Closed",
4178
+ reopened: "Reopened"
4179
+ };
4180
+ function activityLabel(kind) {
4181
+ return ACTIVITY_LABELS[kind];
4182
+ }
4183
+ /**
4184
+ * Which section a card is drawn in.
4185
+ *
4186
+ * Waiting means "bring this back when something changes", so a Waiting review whose change moved
4187
+ * after it was parked is drawn in Active. Derived, and nothing is written: the stored state stays
4188
+ * Waiting until the reviewer says otherwise, and marking it Waiting again moves the baseline.
4189
+ *
4190
+ * Done means "leave me alone", so it never comes back by itself. `created` can never resurface
4191
+ * anything either, because a new analysis is a new record, and a new record is Active.
4192
+ */
4193
+ function sectionOf(lifecycle, activity) {
4194
+ if (!lifecycle) return "active";
4195
+ if (lifecycle.state === "waiting" && changedSince(lifecycle, activity)) return "active";
4196
+ return lifecycle.state;
4197
+ }
4198
+ /** The chip that says why a card is where it is, or absent when its section already says it. */
4199
+ function lifecycleChip(lifecycle, activity) {
4200
+ if (!lifecycle || !changedSince(lifecycle, activity)) return void 0;
4201
+ return lifecycle.state === "waiting" ? "Changed while waiting" : "Changed since done";
4202
+ }
4203
+ function changedSince(lifecycle, activity) {
4204
+ return activity !== void 0 && activity.kind !== "created" && activity.at > lifecycle.at;
4205
+ }
4206
+ /**
4207
+ * Which lifecycle items a card's menu offers.
4208
+ *
4209
+ * Every state but the one the card is already in, which would be an item that does nothing. A card
4210
+ * carrying a chip is the exception and offers all three: re-marking it is how the reviewer says
4211
+ * they have seen the change, so "Mark waiting" on a Waiting review that changed is the settle
4212
+ * action, not a no-op.
4213
+ */
4214
+ function offersLifecycle(target, lifecycle, activity) {
4215
+ if (lifecycleChip(lifecycle, activity) !== void 0) return true;
4216
+ return target !== (lifecycle?.state ?? "active");
4217
+ }
4218
+ //#endregion
4115
4219
  //#region ../../packages/review-harness/src/workspace/store.ts
4116
4220
  var WORKSPACES_DIR = join(STORE_ROOT, "workspaces");
4117
4221
  /**
@@ -4481,8 +4585,20 @@ function followedRefName(branch, followedRef) {
4481
4585
  * can return is the two added together. Neither constant says that on its own, which is why it is
4482
4586
  * said here.
4483
4587
  */
4484
- function indexReviewGroups(limit, keptLimit, keptIds) {
4485
- return selectIndexGroups(groupByLineage(recentWorkspaces(Number.MAX_SAFE_INTEGER)), limit, keptLimit, keptIds);
4588
+ function indexReviewGroups(limit, keptLimit, keptIds, rank, groups = groupByLineage(recentWorkspaces(Number.MAX_SAFE_INTEGER))) {
4589
+ return selectIndexGroups(groups, limit, keptLimit, keptIds, rank);
4590
+ }
4591
+ /**
4592
+ * What the reviewer explicitly kept, which is what stops the recency window hiding it: the queue,
4593
+ * Saved, and anything marked Waiting or Done.
4594
+ *
4595
+ * Done is the reviewer's archive, and an archive the recency window can empty is not one. Waiting
4596
+ * is work they expect back, and a push to it must have a card to come back on.
4597
+ */
4598
+ function indexKeptIds(reviews, queue) {
4599
+ const kept = new Set(queue);
4600
+ for (const review of reviews) if (review.pinned || review.lifecycle !== void 0) kept.add(review.id);
4601
+ return kept;
4486
4602
  }
4487
4603
  /**
4488
4604
  * The choosing, with the disk left out, in the same spirit as `groupByLineage` next door.
@@ -4494,12 +4610,18 @@ function indexReviewGroups(limit, keptLimit, keptIds) {
4494
4610
  *
4495
4611
  * The kept side is capped for the same reason the recent side is: `queue.json` is a file on a disk
4496
4612
  * somebody can edit, and an uncapped read of it is an index with five thousand cards on it.
4613
+ *
4614
+ * **Windowed by `rank`, which is what the list is ordered by.** The index passes what last happened
4615
+ * to each change, so a branch analysed two months ago and pushed to this morning is inside the
4616
+ * window rather than cut before its activity is ever looked at. Absent, it is when the newest
4617
+ * review was made, which is what every other caller has always meant by recent.
4497
4618
  */
4498
- function selectIndexGroups(groups, limit, keptLimit, keptIds) {
4619
+ function selectIndexGroups(groups, limit, keptLimit, keptIds, rank = (group) => group.latest.createdAt) {
4499
4620
  const kept = [];
4500
4621
  const rest = [];
4501
4622
  for (const group of groups) (group.history.some((review) => keptIds.has(review.id)) ? kept : rest).push(group);
4502
- return [...rest.slice(0, limit), ...kept.slice(0, keptLimit)].sort((a, b) => b.latest.createdAt - a.latest.createdAt);
4623
+ const byRank = (a, b) => rank(b) - rank(a);
4624
+ return [...rest.sort(byRank).slice(0, limit), ...kept.sort(byRank).slice(0, keptLimit)].sort(byRank);
4503
4625
  }
4504
4626
  /**
4505
4627
  * The grouping itself, with the disk left out.
@@ -4626,6 +4748,7 @@ function summarise(workspace) {
4626
4748
  lastViewedAt: workspace.lastViewedAt,
4627
4749
  completedAt: workspace.completedAt,
4628
4750
  pinned: workspace.pinned === true,
4751
+ lifecycle: parseLifecycle(workspace.lifecycle),
4629
4752
  paths: files.slice(0, MAX_INDEXED_PATHS).map((file) => file.name),
4630
4753
  prNumber: workspace.changeSet.data.pullRequest?.number || workspace.prContext?.pullRequest.number,
4631
4754
  commitSha: workspace.session.metadata?.commitSha || (workspace.changeSet.targetType === "commit" ? workspace.changeSet.data.pullRequest.head.sha : "") || void 0,
@@ -4803,7 +4926,8 @@ function isKept(entry, queued) {
4803
4926
  const id = workspaceIdFrom(entry);
4804
4927
  if (id === null) return false;
4805
4928
  if (queued.has(id)) return true;
4806
- return loadWorkspace(id)?.pinned === true;
4929
+ const workspace = loadWorkspace(id);
4930
+ return workspace?.pinned === true || parseLifecycle(workspace?.lifecycle)?.state === "done";
4807
4931
  }
4808
4932
  /** The review an entry belongs to, whether it is the record or the usage sidecar beside it. */
4809
4933
  function workspaceIdFrom(entry) {
@@ -12651,4 +12775,4 @@ function lineageIds(id) {
12651
12775
  return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
12652
12776
  }
12653
12777
  //#endregion
12654
- export { queueForReview as $, positionInLineage as $t, createPrState as A, writeAgentPreference as An, allJobs as At, toneOf as B, purposeOf as Bt, readEvents as C, displayRef as Cn, forgeFor as Ct, announceJob as D, resolveModel as Dn, checkReview as Dt, telemetryUploadConsent as E, resolveAgent as En, checkCodeFreshness as Et, markAllRead as F, agentById as Fn, saveJob as Ft, extractJsonText as G, groupByLineage as Gt, withUsageRecorded as H, driverGone as Ht, markRead as I, agentFor as In, PHASES as It, readMarker as J, lineageKeyFor as Jt, ReviewBeingDeletedError as K, indexReviewGroups as Kt, pruneNotifications as L, detectAgents as Ln, isLiveJob as Lt, eventName as M, STORE_ROOT as Mn, fail as Mt, headline as N, AGENT_IDS as Nn, isTerminal as Nt, branchOf as O, clearAgentPreference as On, followedBranch as Ot, listNotifications as P, DEFAULT_AGENT_ID as Pn, loadJob as Pt, compactQueue as Q, mutateWorkspace as Qt, readNotification as R, AgentCancelledError as Rn, phasesFor as Rt, startJob as S, resolveTarget as Sn, forgeResolver as St, recordTelemetryUploadConsent as T, git as Tn, fillFileUrlTemplate as Tt, EXPLAIN_SIMPLY_PROMPT as U, isClaimed as Ut, unreadCount as V, clearClaim as Vt, asString as W, followedRefName as Wt, modelHelpLines as X, loadWorkspace as Xt, removeWorktree as Y, lineagePosition as Yt, relativeTime as Z, matchingWorkspaceIds as Zt, agentEnvOf as _, issuesOutstanding as _n, parseWorkspacePort as _t, wasBlocked as a, touchWorkspace as an, reviewsUrl as at, reanalyseReview as b, processDiscussion as bn, writePortPreference as bt, RefreshUnavailableError as c, dequeueOnComplete as cn, stopServer as ct, refreshPrContext as d, queueRemove as dn, BUILD_VERSION as dt, previousKissResult as en, readIndexToken as et, isUnchanged as f, queueStamp as fn, PACKAGE_NAME as ft, runningJobs as g, isQuestionOutstanding as gn, MIN_WORKSPACE_PORT as gt, liveUpdateFor as h, isIssueOutstanding as hn, MAX_WORKSPACE_PORT as ht, liveJobsFor as i, summarise as in, readServerRecord as it, createPrUpdate as j, CONFIG_PATH as jn, endedAt as jt, subjectOf as k, readAgentPreference as kn, reviewedShaOf as kt, mergeUpdateInto as l, queueAdd as ln, workspaceUrl as lt, UpdateAlreadyRunningError as m, doneVerb as mn, DEFAULT_WORKSPACE_PORT as mt, deleteReview as n, reviewedCommit as nn, clearServerRecord as nt, discardJob as o, workspaceRevision as on, serverEntryExists as ot, askCheckout as p, readQueue as pn, feedbackUrl as pt, MANAGED_ROOT as q, latestKissRun as qt, lineageIds as r, reviewedRepositories as rn, ensureServer as rt, FETCH_TIMEOUT_MS as s, workspaceStamps as sn, spawnServer as st, deleteLineage as t, recentWorkspaces as tn, bootstrapUrl as tt, updateReview as u, queueAddMany as un, writeServerRecord as ut, recordKissRun as v, questionsOutstanding as vn, resolveWorkspacePort as vt, record as w, isCommitReview as wn, remoteHost as wt, runJob as x, describeAuthorship as xn, claimRequestUrl as xt, startKissJob as y, reviewerDispositions as yn, statedWorkspacePort as yt, removeNotification as z, AgentUnavailableError as zn, progressSteps as zt };
12778
+ export { queueForReview as $, mutateWorkspace as $t, createPrState as A, describeAuthorship as An, allJobs as At, toneOf as B, CONFIG_PATH as Bn, purposeOf as Bt, readEvents as C, doneVerb as Cn, forgeFor as Ct, announceJob as D, questionsOutstanding as Dn, checkReview as Dt, telemetryUploadConsent as E, issuesOutstanding as En, checkCodeFreshness as Et, markAllRead as F, resolveAgent as Fn, saveJob as Ft, extractJsonText as G, agentFor as Gn, groupByLineage as Gt, withUsageRecorded as H, AGENT_IDS as Hn, driverGone as Ht, markRead as I, resolveModel as In, PHASES as It, readMarker as J, AgentUnavailableError as Jn, latestKissRun as Jt, ReviewBeingDeletedError as K, detectAgents as Kn, indexKeptIds as Kt, pruneNotifications as L, clearAgentPreference as Ln, isLiveJob as Lt, eventName as M, displayRef as Mn, fail as Mt, headline as N, isCommitReview as Nn, isTerminal as Nt, branchOf as O, reviewerDispositions as On, followedBranch as Ot, listNotifications as P, git as Pn, loadJob as Pt, compactQueue as Q, matchingWorkspaceIds as Qt, readNotification as R, readAgentPreference as Rn, phasesFor as Rt, startJob as S, readQueue as Sn, forgeResolver as St, recordTelemetryUploadConsent as T, isQuestionOutstanding as Tn, fillFileUrlTemplate as Tt, EXPLAIN_SIMPLY_PROMPT as U, DEFAULT_AGENT_ID as Un, isClaimed as Ut, unreadCount as V, STORE_ROOT as Vn, clearClaim as Vt, asString as W, agentById as Wn, followedRefName as Wt, modelHelpLines as X, lineagePosition as Xt, removeWorktree as Y, lineageKeyFor as Yt, relativeTime as Z, loadWorkspace as Zt, agentEnvOf as _, dequeueOnComplete as _n, parseWorkspacePort as _t, wasBlocked as a, summarise as an, reviewsUrl as at, reanalyseReview as b, queueRemove as bn, writePortPreference as bt, RefreshUnavailableError as c, workspaceStamps as cn, stopServer as ct, refreshPrContext as d, isLifecycle as dn, BUILD_VERSION as dt, positionInLineage as en, readIndexToken as et, isUnchanged as f, lifecycleAction as fn, PACKAGE_NAME as ft, runningJobs as g, sectionOf as gn, MIN_WORKSPACE_PORT as gt, liveUpdateFor as h, parseLifecycle as hn, MAX_WORKSPACE_PORT as ht, liveJobsFor as i, reviewedRepositories as in, readServerRecord as it, createPrUpdate as j, resolveTarget as jn, endedAt as jt, subjectOf as k, processDiscussion as kn, reviewedShaOf as kt, mergeUpdateInto as l, LIFECYCLES as ln, workspaceUrl as lt, UpdateAlreadyRunningError as m, offersLifecycle as mn, DEFAULT_WORKSPACE_PORT as mt, deleteReview as n, recentWorkspaces as nn, clearServerRecord as nt, discardJob as o, touchWorkspace as on, serverEntryExists as ot, askCheckout as p, lifecycleChip as pn, feedbackUrl as pt, MANAGED_ROOT as q, AgentCancelledError as qn, indexReviewGroups as qt, lineageIds as r, reviewedCommit as rn, ensureServer as rt, FETCH_TIMEOUT_MS as s, workspaceRevision as sn, spawnServer as st, deleteLineage as t, previousKissResult as tn, bootstrapUrl as tt, updateReview as u, activityLabel as un, writeServerRecord as ut, recordKissRun as v, queueAdd as vn, resolveWorkspacePort as vt, record as w, isIssueOutstanding as wn, remoteHost as wt, runJob as x, queueStamp as xn, claimRequestUrl as xt, startKissJob as y, queueAddMany as yn, statedWorkspacePort as yt, removeNotification as z, writeAgentPreference as zn, progressSteps as zt };
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as queueForReview, $t as positionInLineage, An as writeAgentPreference, At as allJobs, Bt as purposeOf, Cn as displayRef, Dn as resolveModel, Dt as checkReview, E as telemetryUploadConsent, En as resolveAgent, Fn as agentById, Gt as groupByLineage, Ht as driverGone, It as PHASES, J as readMarker, Jt as lineageKeyFor, Ln as detectAgents, Mn as STORE_ROOT, Nn as AGENT_IDS, Nt as isTerminal, Pn as DEFAULT_AGENT_ID, Pt as loadJob, Qt as mutateWorkspace, S as startJob, Sn as resolveTarget, St as forgeResolver, T as recordTelemetryUploadConsent, Tn as git, Ut as isClaimed, Vt as clearClaim, Wt as followedRefName, X as modelHelpLines, Xt as loadWorkspace, Y as removeWorktree, Z as relativeTime, Zt as matchingWorkspaceIds, _t as parseWorkspacePort, a as wasBlocked, at as reviewsUrl, b as reanalyseReview, bt as writePortPreference, ct as stopServer, dt as BUILD_VERSION, et as readIndexToken, ft as PACKAGE_NAME, g as runningJobs, gt as MIN_WORKSPACE_PORT, h as liveUpdateFor, ht as MAX_WORKSPACE_PORT, i as liveJobsFor, in as summarise, jn as CONFIG_PATH, kn as readAgentPreference, l as mergeUpdateInto, lt as workspaceUrl, m as UpdateAlreadyRunningError, mt as DEFAULT_WORKSPACE_PORT, n as deleteReview$1, q as MANAGED_ROOT, rn as reviewedRepositories, rt as ensureServer, tn as recentWorkspaces, tt as bootstrapUrl, u as updateReview, v as recordKissRun, w as record$1, x as runJob, yt as statedWorkspacePort, zt as progressSteps } from "./delete_review-lmVdoybL.js";
2
+ import { $ as queueForReview, $t as mutateWorkspace, At as allJobs, Bn as CONFIG_PATH, Bt as purposeOf, Dt as checkReview, E as telemetryUploadConsent, Fn as resolveAgent, Gt as groupByLineage, Hn as AGENT_IDS, Ht as driverGone, In as resolveModel, It as PHASES, J as readMarker, Kn as detectAgents, Mn as displayRef, Nt as isTerminal, Pn as git, Pt as loadJob, Qt as matchingWorkspaceIds, Rn as readAgentPreference, S as startJob, St as forgeResolver, T as recordTelemetryUploadConsent, Un as DEFAULT_AGENT_ID, Ut as isClaimed, Vn as STORE_ROOT, Vt as clearClaim, Wn as agentById, Wt as followedRefName, X as modelHelpLines, Y as removeWorktree, Yt as lineageKeyFor, Z as relativeTime, Zt as loadWorkspace, _t as parseWorkspacePort, a as wasBlocked, an as summarise, at as reviewsUrl, b as reanalyseReview, bt as writePortPreference, ct as stopServer, dt as BUILD_VERSION, en as positionInLineage, et as readIndexToken, ft as PACKAGE_NAME, g as runningJobs, gt as MIN_WORKSPACE_PORT, h as liveUpdateFor, ht as MAX_WORKSPACE_PORT, i as liveJobsFor, in as reviewedRepositories, jn as resolveTarget, l as mergeUpdateInto, lt as workspaceUrl, m as UpdateAlreadyRunningError, mt as DEFAULT_WORKSPACE_PORT, n as deleteReview$1, nn as recentWorkspaces, q as MANAGED_ROOT, rt as ensureServer, tt as bootstrapUrl, u as updateReview, v as recordKissRun, w as record$1, x as runJob, yt as statedWorkspacePort, zn as writeAgentPreference, zt as progressSteps } from "./delete_review-D52wkt66.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";