prreviewbuddy 0.46.0 → 0.49.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 +87 -0
- package/dist/{delete_review-lmVdoybL.js → delete_review-BBjXPfMV.js} +183 -32
- package/dist/main.js +1 -3
- package/dist/server.js +596 -184
- package/package.json +1 -1
- package/static/chunk-BeqgAIrQ.js +1 -1
- package/static/chunk-vvGSmhmc.js +1 -0
- package/static/reviews.js +1 -1
- package/static/settings.js +1 -1
- package/static/shell.css +259 -157
- package/static/workspace.js +62 -62
- package/static/chunk-CmPWaXhU.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,92 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.49.0
|
|
4
|
+
|
|
5
|
+
**Change a review from the review itself.** The **⋯** menu at the top of a review now has
|
|
6
|
+
everything the card's menu on the reviews list has: **Mark reviewed** or **Mark in progress**,
|
|
7
|
+
**Mark waiting**, **Mark done**, **Move to active**, and **Add to review queue** or **Remove from
|
|
8
|
+
review queue**, as well as Save, Copy review ID and Delete. You no longer have to go back to the
|
|
9
|
+
list to park or queue the review you are reading. Waiting, Done and the queue belong to the branch,
|
|
10
|
+
so they are offered on its newest review; an older review of the same branch points you to it.
|
|
11
|
+
|
|
12
|
+
**The top bar says where the review stands.** It shows the files, the size of the change, whether
|
|
13
|
+
the review is up to date, and two labels: **Reviewed** or **In progress**, and **Waiting** or
|
|
14
|
+
**Done** when the review is parked. None of them are buttons. **Check for updates** has moved into
|
|
15
|
+
the **⋯** menu, because the page already checks by itself every minute while you are looking at it
|
|
16
|
+
and whenever you come back to the tab. Its answer, such as "No change", appears where the review's
|
|
17
|
+
freshness is shown.
|
|
18
|
+
|
|
19
|
+
**Check for updates works more than once.** After one check it stayed greyed out until you reloaded
|
|
20
|
+
the page. It now becomes available again as soon as the check finishes, and pressing it while the
|
|
21
|
+
page is checking by itself no longer does nothing: it waits for that check and then runs its own.
|
|
22
|
+
|
|
23
|
+
**The review page keeps up while it is open.** If a Waiting review's branch gets new commits while
|
|
24
|
+
you are looking at it, the page now says **Changed while waiting** within a minute, without a
|
|
25
|
+
reload, and offers **Mark waiting** again. Changes made from the reviews list in another tab show
|
|
26
|
+
up the same way. Adding a review to a full review queue from its page now says the queue is full
|
|
27
|
+
instead of appearing to work.
|
|
28
|
+
|
|
29
|
+
**Reviewed reviews stay in your queue.** Marking a review **Reviewed** no longer takes it out of
|
|
30
|
+
the review queue, from the reviews list or from the review itself. Reviewed records that you have
|
|
31
|
+
been through it, not that you are finished with it; **Waiting** and **Done** are how you say that,
|
|
32
|
+
and they still take a review out of the queue. `prreviewbuddy review --queue` now queues a Reviewed
|
|
33
|
+
review instead of refusing it, and, like adding from the workspace, moves a Waiting or Done review
|
|
34
|
+
back to Active when it goes in.
|
|
35
|
+
|
|
36
|
+
**Buddy AI has its own tab.** It is no longer a button in the top bar. When Buddy AI's panel is
|
|
37
|
+
closed, a **Buddy AI** tab sits on the right edge of the window; press it to open the panel. The
|
|
38
|
+
double arrow in the panel's header closes it.
|
|
39
|
+
|
|
40
|
+
## 0.48.0
|
|
41
|
+
|
|
42
|
+
**Active, Waiting and Done.** A review can now be marked **Waiting**, for when you have done your
|
|
43
|
+
pass and expect another round, or **Done**, for when you are finished with it. The reviews list keeps
|
|
44
|
+
your active reviews at the top, with **Waiting** below them and **Done** below that, folded away. Use
|
|
45
|
+
the **⋯** menu on a card, or select several and use the bar at the bottom. **Move to active** puts a
|
|
46
|
+
review back. This is separate from **Reviewed**, which still records that you have been through it.
|
|
47
|
+
|
|
48
|
+
**Waiting reviews come back when something changes.** If a Waiting review gets new commits, or its
|
|
49
|
+
pull request is merged, closed or reopened, it shows up in the main list again marked **Changed while
|
|
50
|
+
waiting**. Marking it Waiting again puts it back. A Done review never comes back by itself; if it
|
|
51
|
+
changes, it is marked **Changed since done** where it is. Marking a review Waiting starts watching
|
|
52
|
+
it straight away, so a push made soon after still brings it back. Adding a Waiting or Done review to
|
|
53
|
+
your review queue moves it back to Active.
|
|
54
|
+
|
|
55
|
+
**The list no longer reorders when you open a review.** Reviews are ordered by what last happened to
|
|
56
|
+
the change: when it was analysed, when new commits arrived, or when the pull request was merged,
|
|
57
|
+
closed or reopened. The time on each card now says which of those it was, for example "Updated
|
|
58
|
+
2 hours ago" or "Merged 1 day ago". Saved reviews still come first.
|
|
59
|
+
|
|
60
|
+
**Load more instead of pages.** Each section shows fifteen reviews and a **Load more** button for the
|
|
61
|
+
rest. Search and the filters still cover every review, in all three sections.
|
|
62
|
+
|
|
63
|
+
**Done reviews are kept longer.** Like saved reviews, Done reviews are kept for ninety days rather
|
|
64
|
+
than thirty, counting from the last time you opened or marked them.
|
|
65
|
+
|
|
66
|
+
**Light mode.** The workspace now has a light theme as well as the dark one. The rail, the top bars,
|
|
67
|
+
Buddy AI, the reviews list, Notifications and Settings are drawn in pale greys around a white
|
|
68
|
+
review, so the review stays the brightest thing on the screen. Purple is kept for what you have
|
|
69
|
+
chosen and for the main action, as a pale tint rather than a solid block.
|
|
70
|
+
|
|
71
|
+
**Follows your device, or stays put.** Settings has a new **Appearance** section with **System**,
|
|
72
|
+
**Light** and **Dark**. System is the default, and it changes with your device at once, without
|
|
73
|
+
reloading the page, when your Mac switches between light and dark. Choosing a theme shows it on the
|
|
74
|
+
Settings page straight away; **Save changes** keeps it. If you have not chosen, the workspace follows
|
|
75
|
+
your device, so on a Mac set to light it now opens in light mode.
|
|
76
|
+
|
|
77
|
+
**Readable in both.** Every piece of text in the light theme, including timestamps, counts and other
|
|
78
|
+
small details, meets the WCAG 4.5:1 contrast level against whatever it sits on.
|
|
79
|
+
|
|
80
|
+
**Fixed: buttons in a review that went blank on hover.** In the dark theme, pointing at **Open in**
|
|
81
|
+
your editor, **Show more of this file**, **View files**, **Regenerate** or a diagram's zoom buttons
|
|
82
|
+
turned the label white on the white review, so it disappeared. They now keep their dark label.
|
|
83
|
+
|
|
84
|
+
**A clearer message when OpenAI refuses Codex while it is signed in.** If Codex says it is signed in
|
|
85
|
+
but OpenAI answers "Incorrect API key", the review no longer suggests signing in again, and no longer
|
|
86
|
+
suggests looking for an API key of your own: the key in that error is Codex's own. It now suggests
|
|
87
|
+
`codex doctor` to see what Codex is using, and `codex features list` to find an experimental Codex
|
|
88
|
+
feature to turn off, which is what fixed it when we saw it.
|
|
89
|
+
|
|
3
90
|
## 0.46.0
|
|
4
91
|
|
|
5
92
|
**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
|
|
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 (!
|
|
1151
|
-
|
|
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.
|
|
@@ -4074,19 +4089,6 @@ function queueRemove(id) {
|
|
|
4074
4089
|
return updateQueue((current) => current.includes(id) ? current.filter((queued) => queued !== id) : null);
|
|
4075
4090
|
}
|
|
4076
4091
|
/**
|
|
4077
|
-
* The invariant, as one named thing: the queue holds unfinished work only.
|
|
4078
|
-
*
|
|
4079
|
-
* Removing on completion is half of it. The other half is that this **does nothing** when
|
|
4080
|
-
* `complete` is false, and that half only exists as a written rule -- there is no line of code for
|
|
4081
|
-
* it to be visible in. Re-adding there would make membership something inferred from status rather
|
|
4082
|
-
* than chosen, so a reviewer who took a review out of the queue and later moved it back to In
|
|
4083
|
-
* progress would find it queued again with no idea why.
|
|
4084
|
-
*/
|
|
4085
|
-
function dequeueOnComplete(id, complete) {
|
|
4086
|
-
if (!complete) return;
|
|
4087
|
-
queueRemove(id);
|
|
4088
|
-
}
|
|
4089
|
-
/**
|
|
4090
4092
|
* A token for the index's revision, equality only.
|
|
4091
4093
|
*
|
|
4092
4094
|
* The queue changes only when a person deliberately changes it, so unlike a running job's progress
|
|
@@ -4112,6 +4114,115 @@ function normalise(ids) {
|
|
|
4112
4114
|
return seen;
|
|
4113
4115
|
}
|
|
4114
4116
|
//#endregion
|
|
4117
|
+
//#region ../../packages/review-harness/src/workspace/lifecycle.ts
|
|
4118
|
+
/**
|
|
4119
|
+
* What happens next with a change, as the reviewer says it: still in play, parked until something
|
|
4120
|
+
* moves, or finished with.
|
|
4121
|
+
*
|
|
4122
|
+
* A separate axis from New / In progress / Reviewed, which says what the reviewer has *done*. A
|
|
4123
|
+
* change can be reviewed and waiting for another push, or reviewed and done, and one field cannot
|
|
4124
|
+
* hold both answers.
|
|
4125
|
+
*
|
|
4126
|
+
* One registry that the stored type, the card, the menus, the bulk bar and the route all derive
|
|
4127
|
+
* from. Pure on purpose: the reviews page's script imports it to move a card between sections after
|
|
4128
|
+
* a mark, without asking the server for the page again.
|
|
4129
|
+
*/
|
|
4130
|
+
var LIFECYCLES = [
|
|
4131
|
+
{
|
|
4132
|
+
id: "active",
|
|
4133
|
+
name: "Active",
|
|
4134
|
+
action: "Move to active"
|
|
4135
|
+
},
|
|
4136
|
+
{
|
|
4137
|
+
id: "waiting",
|
|
4138
|
+
name: "Waiting",
|
|
4139
|
+
action: "Mark waiting"
|
|
4140
|
+
},
|
|
4141
|
+
{
|
|
4142
|
+
id: "done",
|
|
4143
|
+
name: "Done",
|
|
4144
|
+
action: "Mark done"
|
|
4145
|
+
}
|
|
4146
|
+
];
|
|
4147
|
+
function isLifecycle(value) {
|
|
4148
|
+
return LIFECYCLES.some((lifecycle) => lifecycle.id === value);
|
|
4149
|
+
}
|
|
4150
|
+
/** A stored value read defensively: anything this code did not write reads as Active. */
|
|
4151
|
+
function parseLifecycle(raw) {
|
|
4152
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
4153
|
+
const { state, at } = raw;
|
|
4154
|
+
if (state !== "waiting" && state !== "done" || typeof at !== "number" || !Number.isFinite(at)) return void 0;
|
|
4155
|
+
return {
|
|
4156
|
+
state,
|
|
4157
|
+
at
|
|
4158
|
+
};
|
|
4159
|
+
}
|
|
4160
|
+
function lifecycleAction(lifecycle) {
|
|
4161
|
+
return LIFECYCLES.find((entry) => entry.id === lifecycle).action;
|
|
4162
|
+
}
|
|
4163
|
+
/**
|
|
4164
|
+
* The review page's lifecycle pill, or absent for Active, which says nothing (as an open pull
|
|
4165
|
+
* request says nothing). A parked review that has changed since reads as the card's chip does, so
|
|
4166
|
+
* the page and the list give one answer about the same review.
|
|
4167
|
+
*/
|
|
4168
|
+
function lifecyclePill(lifecycle, activity) {
|
|
4169
|
+
if (!lifecycle) return void 0;
|
|
4170
|
+
const chip = lifecycleChip(lifecycle, activity);
|
|
4171
|
+
if (chip !== void 0) return {
|
|
4172
|
+
text: chip,
|
|
4173
|
+
changed: true
|
|
4174
|
+
};
|
|
4175
|
+
return {
|
|
4176
|
+
text: LIFECYCLES.find((entry) => entry.id === lifecycle.state).name,
|
|
4177
|
+
changed: false
|
|
4178
|
+
};
|
|
4179
|
+
}
|
|
4180
|
+
var ACTIVITY_LABELS = {
|
|
4181
|
+
created: "Created",
|
|
4182
|
+
updated: "Updated",
|
|
4183
|
+
merged: "Merged",
|
|
4184
|
+
closed: "Closed",
|
|
4185
|
+
reopened: "Reopened"
|
|
4186
|
+
};
|
|
4187
|
+
function activityLabel(kind) {
|
|
4188
|
+
return ACTIVITY_LABELS[kind];
|
|
4189
|
+
}
|
|
4190
|
+
/**
|
|
4191
|
+
* Which section a card is drawn in.
|
|
4192
|
+
*
|
|
4193
|
+
* Waiting means "bring this back when something changes", so a Waiting review whose change moved
|
|
4194
|
+
* after it was parked is drawn in Active. Derived, and nothing is written: the stored state stays
|
|
4195
|
+
* Waiting until the reviewer says otherwise, and marking it Waiting again moves the baseline.
|
|
4196
|
+
*
|
|
4197
|
+
* Done means "leave me alone", so it never comes back by itself. `created` can never resurface
|
|
4198
|
+
* anything either, because a new analysis is a new record, and a new record is Active.
|
|
4199
|
+
*/
|
|
4200
|
+
function sectionOf(lifecycle, activity) {
|
|
4201
|
+
if (!lifecycle) return "active";
|
|
4202
|
+
if (lifecycle.state === "waiting" && changedSince(lifecycle, activity)) return "active";
|
|
4203
|
+
return lifecycle.state;
|
|
4204
|
+
}
|
|
4205
|
+
/** The chip that says why a card is where it is, or absent when its section already says it. */
|
|
4206
|
+
function lifecycleChip(lifecycle, activity) {
|
|
4207
|
+
if (!lifecycle || !changedSince(lifecycle, activity)) return void 0;
|
|
4208
|
+
return lifecycle.state === "waiting" ? "Changed while waiting" : "Changed since done";
|
|
4209
|
+
}
|
|
4210
|
+
function changedSince(lifecycle, activity) {
|
|
4211
|
+
return activity !== void 0 && activity.kind !== "created" && activity.at > lifecycle.at;
|
|
4212
|
+
}
|
|
4213
|
+
/**
|
|
4214
|
+
* Which lifecycle items a card's menu offers.
|
|
4215
|
+
*
|
|
4216
|
+
* Every state but the one the card is already in, which would be an item that does nothing. A card
|
|
4217
|
+
* carrying a chip is the exception and offers all three: re-marking it is how the reviewer says
|
|
4218
|
+
* they have seen the change, so "Mark waiting" on a Waiting review that changed is the settle
|
|
4219
|
+
* action, not a no-op.
|
|
4220
|
+
*/
|
|
4221
|
+
function offersLifecycle(target, lifecycle, activity) {
|
|
4222
|
+
if (lifecycleChip(lifecycle, activity) !== void 0) return true;
|
|
4223
|
+
return target !== (lifecycle?.state ?? "active");
|
|
4224
|
+
}
|
|
4225
|
+
//#endregion
|
|
4115
4226
|
//#region ../../packages/review-harness/src/workspace/store.ts
|
|
4116
4227
|
var WORKSPACES_DIR = join(STORE_ROOT, "workspaces");
|
|
4117
4228
|
/**
|
|
@@ -4481,8 +4592,20 @@ function followedRefName(branch, followedRef) {
|
|
|
4481
4592
|
* can return is the two added together. Neither constant says that on its own, which is why it is
|
|
4482
4593
|
* said here.
|
|
4483
4594
|
*/
|
|
4484
|
-
function indexReviewGroups(limit, keptLimit, keptIds) {
|
|
4485
|
-
return selectIndexGroups(
|
|
4595
|
+
function indexReviewGroups(limit, keptLimit, keptIds, rank, groups = groupByLineage(recentWorkspaces(Number.MAX_SAFE_INTEGER))) {
|
|
4596
|
+
return selectIndexGroups(groups, limit, keptLimit, keptIds, rank);
|
|
4597
|
+
}
|
|
4598
|
+
/**
|
|
4599
|
+
* What the reviewer explicitly kept, which is what stops the recency window hiding it: the queue,
|
|
4600
|
+
* Saved, and anything marked Waiting or Done.
|
|
4601
|
+
*
|
|
4602
|
+
* Done is the reviewer's archive, and an archive the recency window can empty is not one. Waiting
|
|
4603
|
+
* is work they expect back, and a push to it must have a card to come back on.
|
|
4604
|
+
*/
|
|
4605
|
+
function indexKeptIds(reviews, queue) {
|
|
4606
|
+
const kept = new Set(queue);
|
|
4607
|
+
for (const review of reviews) if (review.pinned || review.lifecycle !== void 0) kept.add(review.id);
|
|
4608
|
+
return kept;
|
|
4486
4609
|
}
|
|
4487
4610
|
/**
|
|
4488
4611
|
* The choosing, with the disk left out, in the same spirit as `groupByLineage` next door.
|
|
@@ -4494,12 +4617,18 @@ function indexReviewGroups(limit, keptLimit, keptIds) {
|
|
|
4494
4617
|
*
|
|
4495
4618
|
* The kept side is capped for the same reason the recent side is: `queue.json` is a file on a disk
|
|
4496
4619
|
* somebody can edit, and an uncapped read of it is an index with five thousand cards on it.
|
|
4620
|
+
*
|
|
4621
|
+
* **Windowed by `rank`, which is what the list is ordered by.** The index passes what last happened
|
|
4622
|
+
* to each change, so a branch analysed two months ago and pushed to this morning is inside the
|
|
4623
|
+
* window rather than cut before its activity is ever looked at. Absent, it is when the newest
|
|
4624
|
+
* review was made, which is what every other caller has always meant by recent.
|
|
4497
4625
|
*/
|
|
4498
|
-
function selectIndexGroups(groups, limit, keptLimit, keptIds) {
|
|
4626
|
+
function selectIndexGroups(groups, limit, keptLimit, keptIds, rank = (group) => group.latest.createdAt) {
|
|
4499
4627
|
const kept = [];
|
|
4500
4628
|
const rest = [];
|
|
4501
4629
|
for (const group of groups) (group.history.some((review) => keptIds.has(review.id)) ? kept : rest).push(group);
|
|
4502
|
-
|
|
4630
|
+
const byRank = (a, b) => rank(b) - rank(a);
|
|
4631
|
+
return [...rest.sort(byRank).slice(0, limit), ...kept.sort(byRank).slice(0, keptLimit)].sort(byRank);
|
|
4503
4632
|
}
|
|
4504
4633
|
/**
|
|
4505
4634
|
* The grouping itself, with the disk left out.
|
|
@@ -4536,9 +4665,8 @@ function groupByLineage(reviews) {
|
|
|
4536
4665
|
* on an old review is "then what is the current one", and answering it by sending them to the
|
|
4537
4666
|
* index costs them the page they were reading. See `RelatedReview` for what may travel and why.
|
|
4538
4667
|
*/
|
|
4539
|
-
function lineagePosition(workspace) {
|
|
4668
|
+
function lineagePosition(workspace, all = recentWorkspaces(Number.MAX_SAFE_INTEGER)) {
|
|
4540
4669
|
const review = summarise(workspace);
|
|
4541
|
-
const all = recentWorkspaces(Number.MAX_SAFE_INTEGER);
|
|
4542
4670
|
return {
|
|
4543
4671
|
...positionInLineage(review, all),
|
|
4544
4672
|
reviews: relatedReviews(review, all)
|
|
@@ -4626,6 +4754,7 @@ function summarise(workspace) {
|
|
|
4626
4754
|
lastViewedAt: workspace.lastViewedAt,
|
|
4627
4755
|
completedAt: workspace.completedAt,
|
|
4628
4756
|
pinned: workspace.pinned === true,
|
|
4757
|
+
lifecycle: parseLifecycle(workspace.lifecycle),
|
|
4629
4758
|
paths: files.slice(0, MAX_INDEXED_PATHS).map((file) => file.name),
|
|
4630
4759
|
prNumber: workspace.changeSet.data.pullRequest?.number || workspace.prContext?.pullRequest.number,
|
|
4631
4760
|
commitSha: workspace.session.metadata?.commitSha || (workspace.changeSet.targetType === "commit" ? workspace.changeSet.data.pullRequest.head.sha : "") || void 0,
|
|
@@ -4803,7 +4932,8 @@ function isKept(entry, queued) {
|
|
|
4803
4932
|
const id = workspaceIdFrom(entry);
|
|
4804
4933
|
if (id === null) return false;
|
|
4805
4934
|
if (queued.has(id)) return true;
|
|
4806
|
-
|
|
4935
|
+
const workspace = loadWorkspace(id);
|
|
4936
|
+
return workspace?.pinned === true || parseLifecycle(workspace?.lifecycle)?.state === "done";
|
|
4807
4937
|
}
|
|
4808
4938
|
/** The review an entry belongs to, whether it is the record or the usage sidecar beside it. */
|
|
4809
4939
|
function workspaceIdFrom(entry) {
|
|
@@ -7526,9 +7656,10 @@ function compactQueue(stored) {
|
|
|
7526
7656
|
/**
|
|
7527
7657
|
* Put one review on the queue, the way the index's Add does, and say how that went.
|
|
7528
7658
|
*
|
|
7529
|
-
* **A
|
|
7530
|
-
*
|
|
7531
|
-
*
|
|
7659
|
+
* **A Reviewed review is queued like any other.** Reviewed says what the reviewer has done with it,
|
|
7660
|
+
* not that the work is over; that is Done. A Waiting or Done review that goes in is put back in
|
|
7661
|
+
* Active, as it is from the page (`activateQueued`), because asking for it in the queue is asking
|
|
7662
|
+
* to work on it again.
|
|
7532
7663
|
*
|
|
7533
7664
|
* Already queued is `already`, not a move: the same rule `queueAdd` keeps, for the same reason.
|
|
7534
7665
|
*
|
|
@@ -7536,11 +7667,9 @@ function compactQueue(stored) {
|
|
|
7536
7667
|
* was queued would otherwise hold a place, and a live review could be refused as "full" by it.
|
|
7537
7668
|
*/
|
|
7538
7669
|
function queueForReview(id) {
|
|
7539
|
-
|
|
7540
|
-
if (!workspace) return "gone";
|
|
7541
|
-
if (workspace.completedAt !== void 0) return "complete";
|
|
7670
|
+
if (!loadWorkspace(id)) return "gone";
|
|
7542
7671
|
let result = "added";
|
|
7543
|
-
|
|
7672
|
+
const stored = updateQueue((current) => {
|
|
7544
7673
|
const live = current.filter(isLive);
|
|
7545
7674
|
const unchanged = live.length === current.length ? null : live;
|
|
7546
7675
|
if (live.includes(id)) {
|
|
@@ -7552,7 +7681,29 @@ function queueForReview(id) {
|
|
|
7552
7681
|
return unchanged;
|
|
7553
7682
|
}
|
|
7554
7683
|
return [...live, id];
|
|
7555
|
-
})
|
|
7684
|
+
});
|
|
7685
|
+
if (stored === null) return "unsaved";
|
|
7686
|
+
if (result === "added") activateQueued([id], stored);
|
|
7687
|
+
return result;
|
|
7688
|
+
}
|
|
7689
|
+
/**
|
|
7690
|
+
* Queueing a review puts it back in Active.
|
|
7691
|
+
*
|
|
7692
|
+
* The queue is work the reviewer wants surfaced next, and Waiting and Done both say the opposite; a
|
|
7693
|
+
* queued review folded away in Done would be a contradiction the page then has to draw. Parking
|
|
7694
|
+
* takes a review out of the queue, and this is the same rule read the other way. Only what actually
|
|
7695
|
+
* went in: a review refused because the queue was full keeps the lifecycle it had.
|
|
7696
|
+
*
|
|
7697
|
+
* Every way in calls this: a card, the bulk bar, the review's own page and `--queue`.
|
|
7698
|
+
*/
|
|
7699
|
+
function activateQueued(ids, queue) {
|
|
7700
|
+
const queued = new Set(queue);
|
|
7701
|
+
for (const one of ids) {
|
|
7702
|
+
if (!queued.has(one) || loadWorkspace(one)?.lifecycle === void 0) continue;
|
|
7703
|
+
mutateWorkspace(one, (current) => {
|
|
7704
|
+
current.lifecycle = void 0;
|
|
7705
|
+
});
|
|
7706
|
+
}
|
|
7556
7707
|
}
|
|
7557
7708
|
function isLive(id) {
|
|
7558
7709
|
return loadWorkspace(id) !== null;
|
|
@@ -12651,4 +12802,4 @@ function lineageIds(id) {
|
|
|
12651
12802
|
return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
|
|
12652
12803
|
}
|
|
12653
12804
|
//#endregion
|
|
12654
|
-
export {
|
|
12805
|
+
export { compactQueue as $, matchingWorkspaceIds as $t, createPrState as A, processDiscussion as An, reviewedShaOf as At, toneOf as B, writeAgentPreference as Bn, progressSteps as Bt, readEvents as C, readQueue as Cn, forgeResolver as Ct, announceJob as D, issuesOutstanding as Dn, checkCodeFreshness as Dt, telemetryUploadConsent as E, isQuestionOutstanding as En, fillFileUrlTemplate as Et, markAllRead as F, git as Fn, loadJob as Ft, extractJsonText as G, agentById as Gn, followedRefName as Gt, withUsageRecorded as H, STORE_ROOT as Hn, clearClaim as Ht, markRead as I, resolveAgent as In, saveJob as It, readMarker as J, AgentCancelledError as Jn, indexReviewGroups as Jt, ReviewBeingDeletedError as K, agentFor as Kn, groupByLineage as Kt, pruneNotifications as L, resolveModel as Ln, PHASES as Lt, eventName as M, resolveTarget as Mn, endedAt as Mt, headline as N, displayRef as Nn, fail as Nt, branchOf as O, questionsOutstanding as On, checkReview as Ot, listNotifications as P, isCommitReview as Pn, isTerminal as Pt, activateQueued as Q, loadWorkspace as Qt, readNotification as R, clearAgentPreference as Rn, isLiveJob as Rt, startJob as S, queueStamp as Sn, claimRequestUrl as St, recordTelemetryUploadConsent as T, isIssueOutstanding as Tn, remoteHost as Tt, EXPLAIN_SIMPLY_PROMPT as U, AGENT_IDS as Un, driverGone as Ut, unreadCount as V, CONFIG_PATH as Vn, purposeOf as Vt, asString as W, DEFAULT_AGENT_ID as Wn, isClaimed as Wt, modelHelpLines as X, lineageKeyFor as Xt, removeWorktree as Y, AgentUnavailableError as Yn, latestKissRun as Yt, relativeTime as Z, lineagePosition as Zt, agentEnvOf as _, parseLifecycle as _n, MIN_WORKSPACE_PORT as _t, wasBlocked as a, reviewedRepositories as an, readServerRecord as at, reanalyseReview as b, queueAddMany as bn, statedWorkspacePort as bt, RefreshUnavailableError as c, workspaceRevision as cn, spawnServer as ct, refreshPrContext as d, activityLabel as dn, writeServerRecord as dt, mutateWorkspace as en, queueForReview as et, isUnchanged as f, isLifecycle as fn, BUILD_VERSION as ft, runningJobs as g, offersLifecycle as gn, MAX_WORKSPACE_PORT as gt, liveUpdateFor as h, lifecyclePill as hn, DEFAULT_WORKSPACE_PORT as ht, liveJobsFor as i, reviewedCommit as in, ensureServer as it, createPrUpdate as j, describeAuthorship as jn, allJobs as jt, subjectOf as k, reviewerDispositions as kn, followedBranch as kt, mergeUpdateInto as l, workspaceStamps as ln, stopServer as lt, UpdateAlreadyRunningError as m, lifecycleChip as mn, feedbackUrl as mt, deleteReview as n, previousKissResult as nn, bootstrapUrl as nt, discardJob as o, summarise as on, reviewsUrl as ot, askCheckout as p, lifecycleAction as pn, PACKAGE_NAME as pt, MANAGED_ROOT as q, detectAgents as qn, indexKeptIds as qt, lineageIds as r, recentWorkspaces as rn, clearServerRecord as rt, FETCH_TIMEOUT_MS as s, touchWorkspace as sn, serverEntryExists as st, deleteLineage as t, positionInLineage as tn, readIndexToken as tt, updateReview as u, LIFECYCLES as un, workspaceUrl as ut, recordKissRun as v, sectionOf as vn, parseWorkspacePort as vt, record as w, doneVerb as wn, forgeFor as wt, runJob as x, queueRemove as xn, writePortPreference as xt, startKissJob as y, queueAdd as yn, resolveWorkspacePort as yt, removeNotification as z, readAgentPreference as zn, phasesFor as zt };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $
|
|
2
|
+
import { $t as matchingWorkspaceIds, Bn as writeAgentPreference, Bt as progressSteps, Ct as forgeResolver, E as telemetryUploadConsent, Fn as git, Ft as loadJob, Gn as agentById, Gt as followedRefName, Hn as STORE_ROOT, Ht as clearClaim, In as resolveAgent, J as readMarker, Kt as groupByLineage, Ln as resolveModel, Lt as PHASES, Mn as resolveTarget, Nn as displayRef, Ot as checkReview, Pt as isTerminal, Qt as loadWorkspace, S as startJob, T as recordTelemetryUploadConsent, Un as AGENT_IDS, Ut as driverGone, Vn as CONFIG_PATH, Vt as purposeOf, Wn as DEFAULT_AGENT_ID, Wt as isClaimed, X as modelHelpLines, Xt as lineageKeyFor, Y as removeWorktree, Z as relativeTime, _t as MIN_WORKSPACE_PORT, a as wasBlocked, an as reviewedRepositories, b as reanalyseReview, bt as statedWorkspacePort, en as mutateWorkspace, et as queueForReview, ft as BUILD_VERSION, g as runningJobs, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, it as ensureServer, jt as allJobs, l as mergeUpdateInto, lt as stopServer, m as UpdateAlreadyRunningError, n as deleteReview$1, nt as bootstrapUrl, on as summarise, ot as reviewsUrl, pt as PACKAGE_NAME, q as MANAGED_ROOT, qn as detectAgents, rn as recentWorkspaces, tn as positionInLineage, tt as readIndexToken, u as updateReview, ut as workspaceUrl, v as recordKissRun, vt as parseWorkspacePort, w as record$1, x as runJob, xt as writePortPreference, zn as readAgentPreference } from "./delete_review-BBjXPfMV.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";
|
|
@@ -1455,7 +1455,6 @@ function batchQueueLines(rows) {
|
|
|
1455
1455
|
}
|
|
1456
1456
|
function notQueuedBecause(subject, result) {
|
|
1457
1457
|
switch (result) {
|
|
1458
|
-
case "complete": return `${subject} is marked complete. Move it back to In progress in the workspace to queue it.`;
|
|
1459
1458
|
case "full": return `${subject}, because the review queue is full. It holds 50 reviews at most.`;
|
|
1460
1459
|
default: return `${subject}, because the review queue could not be saved.`;
|
|
1461
1460
|
}
|
|
@@ -1468,7 +1467,6 @@ function reviewQueued(result) {
|
|
|
1468
1467
|
switch (result) {
|
|
1469
1468
|
case "added": return "Added to review queue.";
|
|
1470
1469
|
case "already": return "Already in your review queue.";
|
|
1471
|
-
case "complete": return "Not added to your review queue: this review is marked complete. Move it back to In progress in the workspace to queue it.";
|
|
1472
1470
|
case "full": return `Not added to your review queue: it is full, and holds 50 reviews at most.`;
|
|
1473
1471
|
default: return "Not added to your review queue: the queue could not be saved.";
|
|
1474
1472
|
}
|