prreviewbuddy 0.27.2 → 0.29.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/CHANGELOG.md +50 -0
- package/dist/{delete_review-B3xciJ03.js → delete_review-DUCSC5Bc.js} +200 -11
- package/dist/main.js +1 -1
- package/dist/server.js +245 -41
- package/package.json +1 -1
- package/static/reviews.js +1 -1
- package/static/shell.css +72 -1
- package/static/workspace.js +29 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.29.1
|
|
4
|
+
|
|
5
|
+
**Icons in the review sidebar.** Every item in a review's sidebar now has an icon: Review, KISS,
|
|
6
|
+
Issues, Questions, Files, PR context, Diagrams, Recommendations, and the links at the bottom. All
|
|
7
|
+
reviews and Settings had small text symbols before; they now have full-size icons like the rest.
|
|
8
|
+
The themes in the review path keep their numbers.
|
|
9
|
+
|
|
10
|
+
**Review path themes start collapsed.** On a review's path page, each theme now opens folded to
|
|
11
|
+
its title, priority and size, so you can see the whole path at a glance. Click a theme to open it,
|
|
12
|
+
or choose it in the sidebar to jump straight to it opened.
|
|
13
|
+
|
|
14
|
+
## 0.29.0
|
|
15
|
+
|
|
16
|
+
**Filter your reviews by author.** The reviews list has a dropdown beside the search that lists
|
|
17
|
+
everyone whose pull requests you have reviewed. Choose someone and the list shows only their
|
|
18
|
+
reviews. It works together with the filters beside it, so you can see, say, everything of one
|
|
19
|
+
person's that is still in progress. Reviews of a local branch with no pull request have no GitHub
|
|
20
|
+
username, so they show under Everyone only.
|
|
21
|
+
|
|
22
|
+
**Mark a review reviewed from the list.** Each review's menu in the reviews list now has Mark
|
|
23
|
+
reviewed, so you no longer have to open a review to mark it. Once it is reviewed, the same menu
|
|
24
|
+
offers Mark in progress to undo it. As before, marking a review reviewed takes it out of your
|
|
25
|
+
review queue.
|
|
26
|
+
|
|
27
|
+
**Delete a review from its own page.** The menu at the top of a review now has Delete review,
|
|
28
|
+
with the same confirmation the list uses. It deletes only the review you are looking at, not
|
|
29
|
+
earlier reviews of the same branch, and then takes you back to your reviews. A review that is
|
|
30
|
+
still being analysed cannot be deleted.
|
|
31
|
+
|
|
32
|
+
**Easier to scan sidebar.** In a review's sidebar, Issues, Questions, Files, PR context and the
|
|
33
|
+
links at the bottom are now white, so the review path above them stands out as its own list.
|
|
34
|
+
|
|
35
|
+
## 0.28.0
|
|
36
|
+
|
|
37
|
+
**Save a review, and work through a queue.** The star on each review in your reviews list now
|
|
38
|
+
means Saved. A saved review still sits at the top of the list, and the new Saved filter shows only
|
|
39
|
+
those. For a batch you are working through right now, choose Add to review queue from a review's
|
|
40
|
+
menu: the Queue filter lists them in the order you added them, and Continue reviewing at the top of
|
|
41
|
+
the list opens the first one. Marking a review Reviewed takes it out of the queue. Moving it back
|
|
42
|
+
to In progress does not put it back, so the queue only ever holds what you chose to put there.
|
|
43
|
+
|
|
44
|
+
**Saved and queued reviews are kept for ninety days.** Other reviews are still kept for thirty
|
|
45
|
+
days. The ninety days count from the last time you opened the review, so one you keep coming back
|
|
46
|
+
to stays. A saved review is not kept forever: after ninety days without being opened it is removed
|
|
47
|
+
like any other.
|
|
48
|
+
|
|
49
|
+
**A saved review no longer disappears from the list.** The list shows your fifty most recent
|
|
50
|
+
branches, and a review saved or queued further back than that used to be missing from it
|
|
51
|
+
altogether. Saved and queued reviews are now always listed, in addition to the fifty most recent.
|
|
52
|
+
|
|
3
53
|
## 0.27.2
|
|
4
54
|
|
|
5
55
|
**Choose the model a review runs under.** `prreviewbuddy review --model <model>` asks the agent for
|
|
@@ -3651,10 +3651,135 @@ function doneVerb(counts) {
|
|
|
3651
3651
|
return counts.reviewerClosed > 0 ? "dealt with" : "resolved";
|
|
3652
3652
|
}
|
|
3653
3653
|
//#endregion
|
|
3654
|
+
//#region ../../packages/review-harness/src/workspace/queue.ts
|
|
3655
|
+
/**
|
|
3656
|
+
* The review queue: the set the reviewer is working through now, in the order they chose.
|
|
3657
|
+
*
|
|
3658
|
+
* **Its own file, not a field on `StoredWorkspace`.** The reason is already written at the top of
|
|
3659
|
+
* `store.ts`'s save path: every caller puts back a record it loaded earlier, `runJob` holds one for
|
|
3660
|
+
* an entire analysis, and the write clobbers whatever changed in between without saying so. Queue
|
|
3661
|
+
* membership changed from the index while an analysis was running would simply vanish. A record
|
|
3662
|
+
* also carries the whole diff inline, so a reorder would rewrite megabytes to move one string.
|
|
3663
|
+
*
|
|
3664
|
+
* **Not a key in `ui.json` either**, despite being reviewer state of exactly the kind that file
|
|
3665
|
+
* describes. `preferences.ts` read-modify-writes that file whole, and one unparsable byte in there
|
|
3666
|
+
* currently costs a pane width. Sharing it would make the same byte cost the working set.
|
|
3667
|
+
*
|
|
3668
|
+
* `STORE_ROOT` comes from `store_root.ts` rather than from `store.ts`, which is the import
|
|
3669
|
+
* `preferences.ts` uses. That one is safe only because nothing in `store.ts` imports preferences
|
|
3670
|
+
* back -- and the prune in there *does* import this module, so taking the same shortcut here would
|
|
3671
|
+
* close the cycle.
|
|
3672
|
+
*/
|
|
3673
|
+
var QUEUE_PATH = join(STORE_ROOT, "queue.json");
|
|
3674
|
+
/**
|
|
3675
|
+
* An object rather than a bare array, because an array is the one JSON shape that cannot grow a
|
|
3676
|
+
* sibling field, and "when was this queued" is a plausible second column.
|
|
3677
|
+
*
|
|
3678
|
+
* `version` is not branched on today. It exists so that a later shape change is a decision rather
|
|
3679
|
+
* than a guess about what an old file meant.
|
|
3680
|
+
*/
|
|
3681
|
+
var VERSION = 1;
|
|
3682
|
+
/**
|
|
3683
|
+
* What is queued, in order.
|
|
3684
|
+
*
|
|
3685
|
+
* Best-effort in the same way as `readPreferences`, and for the same reason: missing, unreadable
|
|
3686
|
+
* and corrupt all mean "nothing queued", and none of them is worth an error standing between the
|
|
3687
|
+
* reviewer and the list. Position is the array index throughout -- never stored per entry, because
|
|
3688
|
+
* two representations of one order eventually disagree about it.
|
|
3689
|
+
*/
|
|
3690
|
+
function readQueue() {
|
|
3691
|
+
try {
|
|
3692
|
+
const parsed = JSON.parse(readFileSync(QUEUE_PATH, "utf8"));
|
|
3693
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
|
|
3694
|
+
const ids = parsed.ids;
|
|
3695
|
+
return Array.isArray(ids) ? normalise(ids) : [];
|
|
3696
|
+
} catch {
|
|
3697
|
+
return [];
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* Store a queue, and say what was stored.
|
|
3702
|
+
*
|
|
3703
|
+
* The return is what landed on disk, which is not necessarily what was handed in -- duplicates are
|
|
3704
|
+
* collapsed and the cap applies. Same contract as the prompt bank: the caller gets the list as
|
|
3705
|
+
* stored so a page can paint the truth rather than its own request.
|
|
3706
|
+
*
|
|
3707
|
+
* `null` on a write failure, and that is the point at which this stops resembling `preferences.ts`.
|
|
3708
|
+
* A pane width that fails to save costs one session and nothing depends on it. A queue entry that
|
|
3709
|
+
* fails to save is contradicted by a pill showing a count and by a button that navigates somewhere,
|
|
3710
|
+
* so the caller has to be able to tell the reviewer it did not happen.
|
|
3711
|
+
*/
|
|
3712
|
+
function writeQueue(ids) {
|
|
3713
|
+
const next = normalise(ids);
|
|
3714
|
+
try {
|
|
3715
|
+
mkdirSync(STORE_ROOT, { recursive: true });
|
|
3716
|
+
writeFileSync(QUEUE_PATH, `${JSON.stringify({
|
|
3717
|
+
version: VERSION,
|
|
3718
|
+
ids: next
|
|
3719
|
+
}, null, 2)}\n`);
|
|
3720
|
+
return next;
|
|
3721
|
+
} catch {
|
|
3722
|
+
return null;
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
/**
|
|
3726
|
+
* Append, and leave a review already queued exactly where it is.
|
|
3727
|
+
*
|
|
3728
|
+
* Adding something twice is a no-op rather than a move. Nothing in this UI reorders a queue, so a
|
|
3729
|
+
* second Add that silently promoted a review would be the only control in the product that did --
|
|
3730
|
+
* and it would do it without ever saying so.
|
|
3731
|
+
*/
|
|
3732
|
+
function queueAdd(id) {
|
|
3733
|
+
const current = readQueue();
|
|
3734
|
+
if (current.includes(id)) return current;
|
|
3735
|
+
return writeQueue([...current, id]);
|
|
3736
|
+
}
|
|
3737
|
+
function queueRemove(id) {
|
|
3738
|
+
const current = readQueue();
|
|
3739
|
+
if (!current.includes(id)) return current;
|
|
3740
|
+
return writeQueue(current.filter((queued) => queued !== id));
|
|
3741
|
+
}
|
|
3742
|
+
/**
|
|
3743
|
+
* The invariant, as one named thing: the queue holds unfinished work only.
|
|
3744
|
+
*
|
|
3745
|
+
* Removing on completion is half of it. The other half is that this **does nothing** when
|
|
3746
|
+
* `complete` is false, and that half only exists as a written rule -- there is no line of code for
|
|
3747
|
+
* it to be visible in. Re-adding there would make membership something inferred from status rather
|
|
3748
|
+
* than chosen, so a reviewer who took a review out of the queue and later moved it back to In
|
|
3749
|
+
* progress would find it queued again with no idea why.
|
|
3750
|
+
*/
|
|
3751
|
+
function dequeueOnComplete(id, complete) {
|
|
3752
|
+
if (!complete) return;
|
|
3753
|
+
queueRemove(id);
|
|
3754
|
+
}
|
|
3755
|
+
/**
|
|
3756
|
+
* A token for the index's revision, equality only.
|
|
3757
|
+
*
|
|
3758
|
+
* The queue changes only when a person deliberately changes it, so unlike a running job's progress
|
|
3759
|
+
* this cannot make the page reload itself in a loop. Absent reads as a stable empty string rather
|
|
3760
|
+
* than as a change, for the reason `refreshAction` gives: a missing field that reads as "different"
|
|
3761
|
+
* is a reload that asks again and reloads again.
|
|
3762
|
+
*/
|
|
3763
|
+
function queueStamp() {
|
|
3764
|
+
try {
|
|
3765
|
+
return String(statSync(QUEUE_PATH).mtimeMs);
|
|
3766
|
+
} catch {
|
|
3767
|
+
return "";
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
/** Strings only, first position wins, and never more than the cap. */
|
|
3771
|
+
function normalise(ids) {
|
|
3772
|
+
const seen = [];
|
|
3773
|
+
for (const id of ids) {
|
|
3774
|
+
if (typeof id !== "string" || id === "" || seen.includes(id)) continue;
|
|
3775
|
+
seen.push(id);
|
|
3776
|
+
if (seen.length === 50) break;
|
|
3777
|
+
}
|
|
3778
|
+
return seen;
|
|
3779
|
+
}
|
|
3780
|
+
//#endregion
|
|
3654
3781
|
//#region ../../packages/review-harness/src/workspace/store.ts
|
|
3655
3782
|
var WORKSPACES_DIR = join(STORE_ROOT, "workspaces");
|
|
3656
|
-
/** Reviews older than this are cleared on write. A review of a branch from a month ago is history. */
|
|
3657
|
-
var MAX_AGE_MS = 2592e6;
|
|
3658
3783
|
function workspacePath(id) {
|
|
3659
3784
|
return join(WORKSPACES_DIR, `${id}.json`);
|
|
3660
3785
|
}
|
|
@@ -3944,14 +4069,38 @@ function followedRefName(branch, followedRef) {
|
|
|
3944
4069
|
return followedRef;
|
|
3945
4070
|
}
|
|
3946
4071
|
/**
|
|
3947
|
-
* The index's list:
|
|
4072
|
+
* The index's list: recent branches, plus the ones the reviewer explicitly kept.
|
|
4073
|
+
*
|
|
4074
|
+
* `recentReviewGroups` above is a pure recency window, and it stays that way because other callers
|
|
4075
|
+
* want exactly that. This is the index's own question, and it is a different one, because Saved and
|
|
4076
|
+
* Queue exist to defeat recency: a review saved three weeks ago has to be reachable from the list
|
|
4077
|
+
* or the pill that claims to show it is simply broken.
|
|
4078
|
+
*
|
|
4079
|
+
* **Two windows, and the page shows their sum.** Drawing both from one limit would mean saving
|
|
4080
|
+
* eleven reviews pushed eleven recent ones off the page -- the working set eating the list it was
|
|
4081
|
+
* added to. So `limit` bounds recency, `keptLimit` bounds what was kept, and the most cards this
|
|
4082
|
+
* can return is the two added together. Neither constant says that on its own, which is why it is
|
|
4083
|
+
* said here.
|
|
4084
|
+
*/
|
|
4085
|
+
function indexReviewGroups(limit, keptLimit, keptIds) {
|
|
4086
|
+
return selectIndexGroups(groupByLineage(recentWorkspaces(Number.MAX_SAFE_INTEGER)), limit, keptLimit, keptIds);
|
|
4087
|
+
}
|
|
4088
|
+
/**
|
|
4089
|
+
* The choosing, with the disk left out, in the same spirit as `groupByLineage` next door.
|
|
4090
|
+
*
|
|
4091
|
+
* Membership is tested against a group's **whole history** rather than its newest review. A pin is
|
|
4092
|
+
* written on whichever review the star was clicked on, so a review saved and then re-analysed
|
|
4093
|
+
* carries its pin on the older entry; asking only `latest` would lose the card at exactly the
|
|
4094
|
+
* moment the reviewer was most likely to want it.
|
|
3948
4095
|
*
|
|
3949
|
-
* The
|
|
3950
|
-
*
|
|
3951
|
-
* that has five, which is worse than showing no count at all.
|
|
4096
|
+
* The kept side is capped for the same reason the recent side is: `queue.json` is a file on a disk
|
|
4097
|
+
* somebody can edit, and an uncapped read of it is an index with five thousand cards on it.
|
|
3952
4098
|
*/
|
|
3953
|
-
function
|
|
3954
|
-
|
|
4099
|
+
function selectIndexGroups(groups, limit, keptLimit, keptIds) {
|
|
4100
|
+
const kept = [];
|
|
4101
|
+
const rest = [];
|
|
4102
|
+
for (const group of groups) (group.history.some((review) => keptIds.has(review.id)) ? kept : rest).push(group);
|
|
4103
|
+
return [...rest.slice(0, limit), ...kept.slice(0, keptLimit)].sort((a, b) => b.latest.createdAt - a.latest.createdAt);
|
|
3955
4104
|
}
|
|
3956
4105
|
/**
|
|
3957
4106
|
* The grouping itself, with the disk left out.
|
|
@@ -4076,7 +4225,8 @@ function summarise(workspace) {
|
|
|
4076
4225
|
paths: files.slice(0, MAX_INDEXED_PATHS).map((file) => file.name),
|
|
4077
4226
|
prNumber: workspace.changeSet.data.pullRequest?.number || workspace.prContext?.pullRequest.number,
|
|
4078
4227
|
commitSha: workspace.session.metadata?.commitSha || void 0,
|
|
4079
|
-
author: describeAuthorship(workspace.changeSet, workspace.prContext?.pullRequest)?.label
|
|
4228
|
+
author: describeAuthorship(workspace.changeSet, workspace.prContext?.pullRequest)?.label,
|
|
4229
|
+
authorHandle: workspace.prContext?.pullRequest.author?.handle || void 0
|
|
4080
4230
|
};
|
|
4081
4231
|
}
|
|
4082
4232
|
/**
|
|
@@ -4185,14 +4335,53 @@ function touchWorkspace(workspace) {
|
|
|
4185
4335
|
saveWorkspace(workspace);
|
|
4186
4336
|
} catch {}
|
|
4187
4337
|
}
|
|
4338
|
+
/**
|
|
4339
|
+
* Housekeeping, in two tiers.
|
|
4340
|
+
*
|
|
4341
|
+
* The cheap gate comes first: anything inside the ordinary window is not a candidate under either
|
|
4342
|
+
* tier, so the great majority of files never reach the read below. Only those already past thirty
|
|
4343
|
+
* days pay for a parse -- and a parse here is over a record holding an entire diff, which is why
|
|
4344
|
+
* that ordering is load-bearing rather than tidy.
|
|
4345
|
+
*
|
|
4346
|
+
* The loop walks the directory without filtering by extension, which is what makes the suffix rule
|
|
4347
|
+
* matter: `<id>.tokens.jsonl` ages on its own mtime, and stripping only `.json` would leave a saved
|
|
4348
|
+
* review holding its record while its usage history was quietly deleted from under it. The tier
|
|
4349
|
+
* belongs to the review, not to the file.
|
|
4350
|
+
*
|
|
4351
|
+
* Exported for `retention.test.ts`. It is a real unit with a rule worth stating in cases, and the
|
|
4352
|
+
* alternative -- reaching it only through `createWorkspace` -- would test the retention policy
|
|
4353
|
+
* through a function that exists to do something else.
|
|
4354
|
+
*/
|
|
4188
4355
|
function pruneOldWorkspaces() {
|
|
4189
4356
|
try {
|
|
4357
|
+
const queued = new Set(readQueue());
|
|
4190
4358
|
for (const entry of readdirSync(WORKSPACES_DIR)) {
|
|
4191
4359
|
const path = join(WORKSPACES_DIR, entry);
|
|
4192
|
-
|
|
4360
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
4361
|
+
if (age <= 2592e6) continue;
|
|
4362
|
+
if (age <= 7776e6 && isKept(entry, queued)) continue;
|
|
4363
|
+
unlinkSync(path);
|
|
4193
4364
|
}
|
|
4194
4365
|
} catch {}
|
|
4195
4366
|
}
|
|
4367
|
+
/**
|
|
4368
|
+
* Whether the reviewer said to keep this one, asked of a directory entry rather than of a record.
|
|
4369
|
+
*
|
|
4370
|
+
* A record that will not parse cannot claim to be saved, so it falls to the ordinary window. That
|
|
4371
|
+
* is the safe direction: the alternative keeps unreadable files for three months on the strength of
|
|
4372
|
+
* a question nobody could answer.
|
|
4373
|
+
*/
|
|
4374
|
+
function isKept(entry, queued) {
|
|
4375
|
+
const id = workspaceIdFrom(entry);
|
|
4376
|
+
if (id === null) return false;
|
|
4377
|
+
if (queued.has(id)) return true;
|
|
4378
|
+
return loadWorkspace(id)?.pinned === true;
|
|
4379
|
+
}
|
|
4380
|
+
/** The review an entry belongs to, whether it is the record or the usage sidecar beside it. */
|
|
4381
|
+
function workspaceIdFrom(entry) {
|
|
4382
|
+
for (const suffix of [".tokens.jsonl", ".json"]) if (entry.endsWith(suffix)) return entry.slice(0, -suffix.length);
|
|
4383
|
+
return null;
|
|
4384
|
+
}
|
|
4196
4385
|
//#endregion
|
|
4197
4386
|
//#region ../../packages/review-harness/src/workspace/exclusive_claim.ts
|
|
4198
4387
|
/**
|
|
@@ -11383,4 +11572,4 @@ function lineageIds(id) {
|
|
|
11383
11572
|
return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
|
|
11384
11573
|
}
|
|
11385
11574
|
//#endregion
|
|
11386
|
-
export { fillFileUrlTemplate as $,
|
|
11575
|
+
export { fillFileUrlTemplate as $, writeAgentPreference as $t, removeWorktree as A, workspaceRevision as At, workspaceUrl as B, isQuestionOutstanding as Bt, recordTelemetryUploadConsent as C, previousKissResult as Ct, ReviewBeingDeletedError as D, saveWorkspace as Dt, EXPLAIN_SIMPLY_PROMPT as E, reviewedRepositories as Et, clearServerRecord as F, queueStamp as Ft, DEFAULT_WORKSPACE_PORT as G, describeAuthorship as Gt, BUILD_VERSION as H, questionsOutstanding as Ht, ensureServer as I, readQueue as It, parseWorkspacePort as J, git as Jt, MAX_WORKSPACE_PORT as K, resolveTarget as Kt, readServerRecord as L, writeQueue as Lt, relativeTime as M, dequeueOnComplete as Mt, readIndexToken as N, queueAdd as Nt, MANAGED_ROOT as O, summarise as Ot, bootstrapUrl as P, queueRemove as Pt, forgeResolver as Q, readAgentPreference as Qt, reviewsUrl as R, doneVerb as Rt, record as S, positionInLineage as St, withUsageRecorded as T, reviewedCommit as Tt, PACKAGE_NAME as U, reviewerDispositions as Ut, writeServerRecord as V, issuesOutstanding as Vt, feedbackUrl as W, processDiscussion as Wt, statedWorkspacePort as X, resolveModel as Xt, resolveWorkspacePort as Y, resolveAgent as Yt, writePortPreference as Z, clearAgentPreference as Zt, startKissJob as _, latestKissRun as _t, wasBlocked as a, agentFor as an, isTerminal as at, startJob as b, loadWorkspace as bt, updateReview as c, AgentUnavailableError as cn, PHASES as ct, askCheckout as d, purposeOf as dt, CONFIG_PATH as en, checkCodeFreshness as et, UpdateAlreadyRunningError as f, clearClaim as ft, recordKissRun as g, indexReviewGroups as gt, agentEnvOf as h, groupByLineage as ht, liveJobsFor as i, agentById as in, fail as it, modelHelpLines as j, workspaceStamps as jt, readMarker as k, touchWorkspace as kt, refreshPrContext as l, phasesFor as lt, runningJobs as m, followedRefName as mt, deleteReview as n, AGENT_IDS as nn, allJobs as nt, discardJob as o, detectAgents as on, loadJob as ot, liveUpdateFor as p, isClaimed as pt, MIN_WORKSPACE_PORT as q, displayRef as qt, lineageIds as r, DEFAULT_AGENT_ID as rn, endedAt as rt, RefreshUnavailableError as s, AgentCancelledError as sn, saveJob as st, deleteLineage as t, STORE_ROOT as tn, checkFreshness as tt, isUnchanged as u, progressSteps as ut, reanalyseReview as v, lineageKeyFor as vt, telemetryUploadConsent as w, recentWorkspaces as wt, readEvents as x, matchingWorkspaceIds as xt, runJob as y, lineagePosition as yt, stopServer as z, isIssueOutstanding as zt };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { $t as writeAgentPreference, A as removeWorktree, B as workspaceUrl, C as recordTelemetryUploadConsent, Dt as saveWorkspace, Et as reviewedRepositories, G as DEFAULT_WORKSPACE_PORT, H as BUILD_VERSION, I as ensureServer, J as parseWorkspacePort, Jt as git, K as MAX_WORKSPACE_PORT, Kt as resolveTarget, M as relativeTime, N as readIndexToken, O as MANAGED_ROOT, Ot as summarise, P as bootstrapUrl, Q as forgeResolver, Qt as readAgentPreference, R as reviewsUrl, S as record, St as positionInLineage, U as PACKAGE_NAME, X as statedWorkspacePort, Xt as resolveModel, Yt as resolveAgent, Z as writePortPreference, a as wasBlocked, at as isTerminal, b as startJob, bt as loadWorkspace, c as updateReview, ct as PHASES, dt as purposeOf, en as CONFIG_PATH, f as UpdateAlreadyRunningError, ft as clearClaim, g as recordKissRun, ht as groupByLineage, i as liveJobsFor, in as agentById, j as modelHelpLines, k as readMarker, m as runningJobs, mt as followedRefName, n as deleteReview$1, nn as AGENT_IDS, nt as allJobs, on as detectAgents, ot as loadJob, p as liveUpdateFor, pt as isClaimed, q as MIN_WORKSPACE_PORT, qt as displayRef, rn as DEFAULT_AGENT_ID, tn as STORE_ROOT, tt as checkFreshness, ut as progressSteps, v as reanalyseReview, vt as lineageKeyFor, w as telemetryUploadConsent, wt as recentWorkspaces, xt as matchingWorkspaceIds, y as runJob, z as stopServer } from "./delete_review-DUCSC5Bc.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";
|