prreviewbuddy 0.52.2 → 0.53.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 +38 -0
- package/dist/{delete_review-BiV1aBpx.js → delete_review-DMJXD3bf.js} +175 -82
- package/dist/main.js +1 -1
- package/dist/server.js +357 -57
- package/package.json +1 -1
- package/static/shell.css +145 -22
- package/static/workspace.js +35 -27
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.53.1
|
|
4
|
+
|
|
5
|
+
**The running KISS review has its normal layout back.** While a KISS review ran, its progress
|
|
6
|
+
message sat in a rounded grey pill with the text pressed against its edges. It borrowed the styling
|
|
7
|
+
of the new recommendation status labels, which shared its name.
|
|
8
|
+
|
|
9
|
+
## 0.53.0
|
|
10
|
+
|
|
11
|
+
**KISS recommendations are decisions now.** Each recommendation carries its status and two choices
|
|
12
|
+
worded for whose code it is. Reviewing your own code, you choose **Plan to simplify** or **Keep as
|
|
13
|
+
implemented**. Reviewing someone else's, you choose **Raise with author** or **Leave it**. Decided
|
|
14
|
+
recommendations move into a **Decided** list below the open ones, in the order the analysis ranked
|
|
15
|
+
them. Press the chosen button again to take a decision back. Decisions are kept across reloads, and
|
|
16
|
+
the KISS rail counts what is still undecided. If a decision can't be saved, the card goes back as it
|
|
17
|
+
was and offers **Try again**.
|
|
18
|
+
|
|
19
|
+
- **Copy recommendations** (reviewing someone else's code): copies the recommendations you chose to
|
|
20
|
+
raise as Markdown ready to paste, with each one's title, why it matters, the simpler approach, where
|
|
21
|
+
to start and the draft comment. It is disabled until you choose one, while a decision is still
|
|
22
|
+
being saved, and whenever the branch has moved since the run. If a rerun fails, the earlier review
|
|
23
|
+
stays on the page and is checked against the branch by its own commit, so it is marked stale when
|
|
24
|
+
the branch has moved past it.
|
|
25
|
+
- Each card also has **Copy**, **Ask Buddy**, **Open file** and, where the run wrote one, **Copy
|
|
26
|
+
draft comment**.
|
|
27
|
+
- **Whose code is this?** is now part of running KISS, not part of the result. A finished review
|
|
28
|
+
shows its perspective in the header, beside **Run again**, which opens the choice with the last
|
|
29
|
+
answer already selected. The stale-branch notice offers the same **Run again**, and **Not now**
|
|
30
|
+
now folds that notice to one line instead of removing it.
|
|
31
|
+
- **Complexity worth keeping** is collapsed on the KISS summary. New runs give each item a one-line
|
|
32
|
+
reason beside its title.
|
|
33
|
+
- Fixed: a review finishing in the background could undo something you changed on the page while it
|
|
34
|
+
ran, such as a dismissed notice or an answered question.
|
|
35
|
+
|
|
36
|
+
## 0.52.3
|
|
37
|
+
|
|
38
|
+
**Selected cards keep their rounded corners.** In select mode, a ticked card's tint now fills the
|
|
39
|
+
card's own rounded shape instead of a square behind it.
|
|
40
|
+
|
|
3
41
|
## 0.52.2
|
|
4
42
|
|
|
5
43
|
**Continue reviewing is gone from the Reviews page.** The banner opened whatever was first in your
|
|
@@ -3245,6 +3245,30 @@ function failSession(session, error, kind, rejectedAnswer) {
|
|
|
3245
3245
|
};
|
|
3246
3246
|
}
|
|
3247
3247
|
//#endregion
|
|
3248
|
+
//#region ../../packages/review-harness/src/domain/kiss/identity.ts
|
|
3249
|
+
function distinctIds(items) {
|
|
3250
|
+
const taken = new Set(items.map((item) => item.id));
|
|
3251
|
+
const kept = /* @__PURE__ */ new Set();
|
|
3252
|
+
return items.map((item) => {
|
|
3253
|
+
if (!kept.has(item.id)) {
|
|
3254
|
+
kept.add(item.id);
|
|
3255
|
+
return item;
|
|
3256
|
+
}
|
|
3257
|
+
let n = 2;
|
|
3258
|
+
while (taken.has(`${item.id}~${n}`)) n += 1;
|
|
3259
|
+
const id = `${item.id}~${n}`;
|
|
3260
|
+
taken.add(id);
|
|
3261
|
+
return {
|
|
3262
|
+
...item,
|
|
3263
|
+
id
|
|
3264
|
+
};
|
|
3265
|
+
});
|
|
3266
|
+
}
|
|
3267
|
+
/** A run's recommendations with the ids decisions are stored against. Read through this, always. */
|
|
3268
|
+
function recommendationsOf(result) {
|
|
3269
|
+
return distinctIds(result?.recommendations ?? []);
|
|
3270
|
+
}
|
|
3271
|
+
//#endregion
|
|
3248
3272
|
//#region ../../packages/review-harness/src/domain/content/github/diff_parser.ts
|
|
3249
3273
|
var CONTEXT_LINES = 2;
|
|
3250
3274
|
/**
|
|
@@ -4326,6 +4350,19 @@ var WORKSPACES_DIR = join(STORE_ROOT, "workspaces");
|
|
|
4326
4350
|
* in the minutes it took. `handleState` is the only writer and writes nothing else.
|
|
4327
4351
|
*/
|
|
4328
4352
|
var REVIEWER_SESSION_FIELDS = ["answeredQuestionIds", "dismissedIssues"];
|
|
4353
|
+
/**
|
|
4354
|
+
* A session a long run is about to write, with the reviewer's own fields taken from disk instead.
|
|
4355
|
+
*
|
|
4356
|
+
* The run built `session` from a copy it loaded before awaiting something, and the reviewer may have
|
|
4357
|
+
* answered or dismissed something in that window. Absent on disk means absent here too.
|
|
4358
|
+
*/
|
|
4359
|
+
function keepReviewerFields(fresh, session) {
|
|
4360
|
+
const kept = { ...session };
|
|
4361
|
+
const current = fresh.session;
|
|
4362
|
+
for (const field of REVIEWER_SESSION_FIELDS) if (field in fresh.session) kept[field] = current[field];
|
|
4363
|
+
else delete kept[field];
|
|
4364
|
+
return kept;
|
|
4365
|
+
}
|
|
4329
4366
|
function workspacePath(id) {
|
|
4330
4367
|
return join(WORKSPACES_DIR, `${id}.json`);
|
|
4331
4368
|
}
|
|
@@ -4945,6 +4982,17 @@ function previousKissResult(workspace) {
|
|
|
4945
4982
|
for (let index = before.length - 1; index >= 0; index -= 1) if (before[index].result) return before[index];
|
|
4946
4983
|
return null;
|
|
4947
4984
|
}
|
|
4985
|
+
/**
|
|
4986
|
+
* The run whose answer the page presents: the latest when it produced one, otherwise the last that
|
|
4987
|
+
* did. The store's form of `presentedKissRun` in the view, for callers holding a workspace rather
|
|
4988
|
+
* than a view model. Freshness must be measured from this run's commit: measured from a failed
|
|
4989
|
+
* rerun's instead, an answer about older commits would read as current, and could be handed off.
|
|
4990
|
+
*/
|
|
4991
|
+
function presentedKissRunOf(workspace) {
|
|
4992
|
+
const latest = latestKissRun(workspace);
|
|
4993
|
+
if (latest?.result) return latest;
|
|
4994
|
+
return previousKissResult(workspace);
|
|
4995
|
+
}
|
|
4948
4996
|
/** Appends a run and points the page at it. The caller saves: this is one half of a larger write. */
|
|
4949
4997
|
function startKissRun(workspace, start) {
|
|
4950
4998
|
const run = {
|
|
@@ -5004,6 +5052,38 @@ function failKissRun(workspace, runId, error, kind, rejectedAnswer) {
|
|
|
5004
5052
|
return run;
|
|
5005
5053
|
}
|
|
5006
5054
|
/**
|
|
5055
|
+
* Whether this review holds the recommendation a decision names. Asked before writing, so a refused
|
|
5056
|
+
* decision leaves the file untouched, and again inside the write, where the answer is final.
|
|
5057
|
+
*/
|
|
5058
|
+
function kissDecisionRefusal(workspace, input) {
|
|
5059
|
+
const run = (workspace.kissRuns ?? []).find((candidate) => candidate.id === input.runId);
|
|
5060
|
+
if (!run?.result) return "unknown-run";
|
|
5061
|
+
return recommendationsOf(run.result).some((recommendation) => recommendation.id === input.recommendationId) ? null : "unknown-recommendation";
|
|
5062
|
+
}
|
|
5063
|
+
/**
|
|
5064
|
+
* Record one decision, replacing whatever was decided about that recommendation before.
|
|
5065
|
+
*
|
|
5066
|
+
* One entry per request rather than the page's whole list, so two cards decided in quick
|
|
5067
|
+
* succession cannot overwrite each other: each request changes only the entry it names.
|
|
5068
|
+
*/
|
|
5069
|
+
function decideKissRecommendation(workspace, input, now = Date.now()) {
|
|
5070
|
+
const refusal = kissDecisionRefusal(workspace, input);
|
|
5071
|
+
if (refusal) return refusal;
|
|
5072
|
+
const others = (workspace.kissDecisions ?? []).filter((entry) => !(entry.runId === input.runId && entry.recommendationId === input.recommendationId));
|
|
5073
|
+
workspace.kissDecisions = input.decision === "undecided" ? others : [...others, {
|
|
5074
|
+
runId: input.runId,
|
|
5075
|
+
recommendationId: input.recommendationId,
|
|
5076
|
+
decision: input.decision,
|
|
5077
|
+
decidedAt: now
|
|
5078
|
+
}];
|
|
5079
|
+
return null;
|
|
5080
|
+
}
|
|
5081
|
+
/** The decisions made against one run. Empty for a run nobody has decided anything about. */
|
|
5082
|
+
function kissDecisionsOf(workspace, runId) {
|
|
5083
|
+
if (!runId) return [];
|
|
5084
|
+
return (workspace.kissDecisions ?? []).filter((entry) => entry.runId === runId);
|
|
5085
|
+
}
|
|
5086
|
+
/**
|
|
5007
5087
|
* Record that a workspace was opened.
|
|
5008
5088
|
*
|
|
5009
5089
|
* Best-effort and deliberately silent: a review that cannot record having been looked at is still
|
|
@@ -9505,6 +9585,7 @@ var KISS_OUTPUT_INSTRUCTIONS = `Respond with a single JSON object, no markdown a
|
|
|
9505
9585
|
"justifiedComplexity": [{
|
|
9506
9586
|
"id": string,
|
|
9507
9587
|
"title": string,
|
|
9588
|
+
"reason": string,
|
|
9508
9589
|
"rationale": string,
|
|
9509
9590
|
"locations": [{ "path": string, "line": number, "primary": boolean }]
|
|
9510
9591
|
}],
|
|
@@ -9530,6 +9611,9 @@ Field guidance:
|
|
|
9530
9611
|
- "draftComment": REVIEWER FRAMING ONLY, and only where a comment is worth making. Omit it otherwise. A short, constructive pull request comment in the reviewer's voice.
|
|
9531
9612
|
- "locations": required, at least one. Where this complexity lives. Prefer the changed files responsible for it, named exactly as they appear in the diff. If an unchanged repository file is where the complexity actually sits and no changed file represents it, cite that file too, but never describe an unchanged file as part of this change. "line" is optional. Set "primary": true on exactly one location — the one place a reader should open first, which should be a changed file wherever one represents the concern — and false on the rest.
|
|
9532
9613
|
- "justifiedComplexity": complexity in this change that is doing a real job. Empty list when there is nothing worth the note.
|
|
9614
|
+
- "title": what is kept, as the decision: "Keep atomic replacement", "Keep the schema 1 fallback".
|
|
9615
|
+
- "reason": required. Why it stays, in one sentence of at most 15 words: "Prevents concurrent writers from corrupting persisted state." Shown without expanding anything, so it must carry the point on its own. Do not restate the title.
|
|
9616
|
+
- "rationale": the full supporting explanation, in detail. Point at the code.
|
|
9533
9617
|
- "aggregateEstimate": optional, one phrase, across the whole change. Omit it unless it is defensible.`;
|
|
9534
9618
|
function buildKissPrompt(pr, options) {
|
|
9535
9619
|
const { stats, raw } = pr;
|
|
@@ -9828,10 +9912,10 @@ function parseKissAnswer(raw) {
|
|
|
9828
9912
|
const { kept, withheld } = normalizeRecommendations(obj.recommendations);
|
|
9829
9913
|
return {
|
|
9830
9914
|
result: {
|
|
9831
|
-
schemaVersion:
|
|
9915
|
+
schemaVersion: 3,
|
|
9832
9916
|
assessment,
|
|
9833
9917
|
summary,
|
|
9834
|
-
recommendations: kept,
|
|
9918
|
+
recommendations: distinctIds(kept),
|
|
9835
9919
|
justifiedComplexity: normalizeJustified(obj.justifiedComplexity),
|
|
9836
9920
|
...optional("aggregateEstimate", asString(obj.aggregateEstimate))
|
|
9837
9921
|
},
|
|
@@ -9896,6 +9980,7 @@ function normalizeJustified(value) {
|
|
|
9896
9980
|
return value.filter((item) => typeof item === "object" && item !== null).map((item, index) => ({
|
|
9897
9981
|
id: asString(item.id) || `keep-${index + 1}`,
|
|
9898
9982
|
title: asString(item.title),
|
|
9983
|
+
...optional("reason", unlessPlaceholder(asString(item.reason))),
|
|
9899
9984
|
rationale: asString(item.rationale),
|
|
9900
9985
|
locations: normalizeLocations(item.locations)
|
|
9901
9986
|
})).filter((entry) => entry.title !== "" || entry.rationale !== "");
|
|
@@ -10849,16 +10934,17 @@ async function startJob(input) {
|
|
|
10849
10934
|
} : {}
|
|
10850
10935
|
});
|
|
10851
10936
|
saveJob(job);
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10937
|
+
mutateWorkspace(workspace.id, (fresh) => {
|
|
10938
|
+
if (review.type === "kiss") startKissRun(fresh, {
|
|
10939
|
+
jobId: job.id,
|
|
10940
|
+
audience: review.audience,
|
|
10941
|
+
reviewedSha: target.sha,
|
|
10942
|
+
promptVersion: "3",
|
|
10943
|
+
agentId: agent.id,
|
|
10944
|
+
...input.requestedModel ? { requestedModel: input.requestedModel } : {}
|
|
10945
|
+
});
|
|
10946
|
+
else fresh.jobId = job.id;
|
|
10859
10947
|
});
|
|
10860
|
-
else workspace.jobId = job.id;
|
|
10861
|
-
saveWorkspace(workspace);
|
|
10862
10948
|
});
|
|
10863
10949
|
return workspace.id;
|
|
10864
10950
|
}
|
|
@@ -10881,37 +10967,41 @@ async function reanalyseReview(workspaceId, agentId, onStarted, requestedModel)
|
|
|
10881
10967
|
if (!sha) throw new Error("This review does not record which commit it describes, so it cannot be analysed again.");
|
|
10882
10968
|
const agent = agentId ? agentById(agentId) : agentById(agentIdOf(workspace.session));
|
|
10883
10969
|
const started = await withReviewLock(workspaceId, () => {
|
|
10884
|
-
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10970
|
+
const created = {};
|
|
10971
|
+
mutateWorkspace(workspaceId, (workspace) => {
|
|
10972
|
+
if (workspace.session.result) workspace.previousResult = {
|
|
10973
|
+
result: workspace.session.result,
|
|
10974
|
+
commitSha: sha,
|
|
10975
|
+
replacedAt: Date.now(),
|
|
10976
|
+
agentId: agentIdOf(workspace.session),
|
|
10977
|
+
...workspace.session.requestedModel ? { requestedModel: workspace.session.requestedModel } : {}
|
|
10978
|
+
};
|
|
10979
|
+
const target = {
|
|
10980
|
+
originRepoPath: workspace.repoPath,
|
|
10981
|
+
branch: workspace.changeSet.headRef,
|
|
10982
|
+
sha,
|
|
10983
|
+
...baseOf(workspace.changeSet)
|
|
10984
|
+
};
|
|
10985
|
+
const model = resolveModel({
|
|
10986
|
+
...requestedModel ? { flag: requestedModel } : {},
|
|
10987
|
+
review: { session: workspace.session }
|
|
10988
|
+
});
|
|
10989
|
+
const job = createJob({
|
|
10990
|
+
workspaceId: workspace.id,
|
|
10991
|
+
target,
|
|
10992
|
+
env: agent.captureEnv(),
|
|
10993
|
+
purpose: "review",
|
|
10994
|
+
reanalysis: true,
|
|
10995
|
+
...model ? { requestedModel: model } : {}
|
|
10996
|
+
});
|
|
10997
|
+
saveJob(job);
|
|
10998
|
+
workspace.jobId = job.id;
|
|
10999
|
+
workspace.session = beginReviewSession(sha, agent, void 0, model ?? void 0);
|
|
11000
|
+
dropDerivedFromAnalysis(workspace);
|
|
11001
|
+
created.job = job;
|
|
10908
11002
|
});
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
workspace.session = beginReviewSession(sha, agent, void 0, model ?? void 0);
|
|
10912
|
-
dropDerivedFromAnalysis(workspace);
|
|
10913
|
-
saveWorkspace(workspace);
|
|
10914
|
-
return job;
|
|
11003
|
+
if (!created.job) throw new Error("No such review.");
|
|
11004
|
+
return created.job;
|
|
10915
11005
|
});
|
|
10916
11006
|
if (isBusy(started)) throw new ReviewBeingDeletedError();
|
|
10917
11007
|
onStarted?.(started.id);
|
|
@@ -11038,27 +11128,27 @@ async function drive(jobId, workspaceId, runners, driver, signal) {
|
|
|
11038
11128
|
...job.target.pullRequest ? { requestNumber: job.target.pullRequest.number } : {},
|
|
11039
11129
|
...expectedFor(job.target)
|
|
11040
11130
|
});
|
|
11041
|
-
const stored = loadWorkspace(workspaceId);
|
|
11042
11131
|
const isLinkedWorktree = await linkedWorktree(job.target.originRepoPath);
|
|
11043
11132
|
const checkoutName = basename(job.target.originRepoPath);
|
|
11044
|
-
|
|
11133
|
+
const target = job.target;
|
|
11134
|
+
mutateWorkspace(workspaceId, (stored) => ({
|
|
11045
11135
|
...stored,
|
|
11046
11136
|
changeSet: {
|
|
11047
11137
|
...context.changeSet,
|
|
11048
|
-
repoPath:
|
|
11049
|
-
headRef:
|
|
11050
|
-
...
|
|
11051
|
-
...commitIdentity(
|
|
11138
|
+
repoPath: target.originRepoPath,
|
|
11139
|
+
headRef: target.branch,
|
|
11140
|
+
...target.ref ? { headResolvedRef: target.ref } : {},
|
|
11141
|
+
...commitIdentity(target, stored.changeSet),
|
|
11052
11142
|
checkoutName,
|
|
11053
11143
|
isLinkedWorktree,
|
|
11054
11144
|
data: {
|
|
11055
11145
|
...context.changeSet.data,
|
|
11056
11146
|
pullRequest: {
|
|
11057
11147
|
...context.changeSet.data.pullRequest,
|
|
11058
|
-
number:
|
|
11148
|
+
number: target.pullRequest?.number ?? context.changeSet.data.pullRequest.number,
|
|
11059
11149
|
head: {
|
|
11060
11150
|
...context.changeSet.data.pullRequest.head,
|
|
11061
|
-
ref:
|
|
11151
|
+
ref: target.branch
|
|
11062
11152
|
},
|
|
11063
11153
|
repo: checkoutName
|
|
11064
11154
|
}
|
|
@@ -11066,7 +11156,7 @@ async function drive(jobId, workspaceId, runners, driver, signal) {
|
|
|
11066
11156
|
},
|
|
11067
11157
|
diff: context.diff,
|
|
11068
11158
|
reviewedPaths: context.changeSet.data.files.map((file) => file.name)
|
|
11069
|
-
});
|
|
11159
|
+
}));
|
|
11070
11160
|
job = {
|
|
11071
11161
|
...job,
|
|
11072
11162
|
contextId: context.contextId
|
|
@@ -11099,10 +11189,12 @@ async function drive(jobId, workspaceId, runners, driver, signal) {
|
|
|
11099
11189
|
detail: message(error)
|
|
11100
11190
|
};
|
|
11101
11191
|
}
|
|
11102
|
-
if (outcome.kind === "attached")
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11192
|
+
if (outcome.kind === "attached") {
|
|
11193
|
+
const context = outcome.context;
|
|
11194
|
+
mutateWorkspace(workspaceId, (fresh) => {
|
|
11195
|
+
fresh.prContext = context;
|
|
11196
|
+
});
|
|
11197
|
+
}
|
|
11106
11198
|
}
|
|
11107
11199
|
job = {
|
|
11108
11200
|
...job,
|
|
@@ -11338,15 +11430,17 @@ async function runAnalysisFor(job, workspaceId, runners, signal, onObservedModel
|
|
|
11338
11430
|
*/
|
|
11339
11431
|
async function applyKiss(job, workspaceId, payload, observedModel) {
|
|
11340
11432
|
const stored = loadWorkspace(workspaceId);
|
|
11341
|
-
|
|
11433
|
+
runOfJob(stored, job.id);
|
|
11342
11434
|
const validated = await validateKiss(payload, stored.reviewedPaths, (paths) => existingPaths(job.worktreePath, paths));
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11435
|
+
const provenance = await runProvenanceOf(job, observedModel);
|
|
11436
|
+
mutateWorkspace(workspaceId, (fresh) => {
|
|
11437
|
+
completeKissRun(fresh, runOfJob(fresh, job.id).id, {
|
|
11438
|
+
result: validated.result,
|
|
11439
|
+
audit: validated.audit,
|
|
11440
|
+
...job.env.agentId ? { agentId: job.env.agentId } : {},
|
|
11441
|
+
...provenance
|
|
11442
|
+
});
|
|
11348
11443
|
});
|
|
11349
|
-
saveWorkspace(stored);
|
|
11350
11444
|
}
|
|
11351
11445
|
/**
|
|
11352
11446
|
* Record the failure on the run, if there is still a run in flight to record it on.
|
|
@@ -11358,12 +11452,11 @@ async function applyKiss(job, workspaceId, payload, observedModel) {
|
|
|
11358
11452
|
* declines instead of turning a delivered answer into a failure.
|
|
11359
11453
|
*/
|
|
11360
11454
|
function failCurrentKissRun(workspaceId, job, reason, kind, rejectedAnswer) {
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
saveWorkspace(stored);
|
|
11455
|
+
mutateWorkspace(workspaceId, (stored) => {
|
|
11456
|
+
const run = (stored.kissRuns ?? []).find((candidate) => candidate.jobId === job.id);
|
|
11457
|
+
if (!run || run.status === "completed" || run.status === "failed") return;
|
|
11458
|
+
failKissRun(stored, run.id, reason, kind, rejectedAnswer);
|
|
11459
|
+
});
|
|
11367
11460
|
}
|
|
11368
11461
|
async function applyGuide(job, workspaceId, payload, observedModel) {
|
|
11369
11462
|
const stored = loadWorkspace(workspaceId);
|
|
@@ -11372,18 +11465,22 @@ async function applyGuide(job, workspaceId, payload, observedModel) {
|
|
|
11372
11465
|
try {
|
|
11373
11466
|
applied = await applyGuideToContext(context, payload);
|
|
11374
11467
|
} catch (error) {
|
|
11375
|
-
if (error instanceof GuideRejected)
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11468
|
+
if (error instanceof GuideRejected) {
|
|
11469
|
+
const failed = failSession(stored.session, error.message, "agent_output_invalid", error.answer);
|
|
11470
|
+
mutateWorkspace(workspaceId, (fresh) => ({
|
|
11471
|
+
...fresh,
|
|
11472
|
+
session: keepReviewerFields(fresh, failed)
|
|
11473
|
+
}));
|
|
11474
|
+
}
|
|
11379
11475
|
throw error;
|
|
11380
11476
|
}
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11477
|
+
const session = completeReviewSession(stored.session, applied.result, context, { run: await runProvenanceOf(job, observedModel) });
|
|
11478
|
+
mutateWorkspace(workspaceId, (fresh) => ({
|
|
11479
|
+
...fresh,
|
|
11480
|
+
session: keepReviewerFields(fresh, session),
|
|
11384
11481
|
audit: applied.audit,
|
|
11385
11482
|
referencedFiles: applied.referencedFiles
|
|
11386
|
-
});
|
|
11483
|
+
}));
|
|
11387
11484
|
}
|
|
11388
11485
|
/**
|
|
11389
11486
|
* How the run that just finished was made, as the session should record it.
|
|
@@ -11458,7 +11555,7 @@ async function recordKissRun(input) {
|
|
|
11458
11555
|
jobId: job.id,
|
|
11459
11556
|
audience: input.audience,
|
|
11460
11557
|
reviewedSha: sha,
|
|
11461
|
-
promptVersion: "
|
|
11558
|
+
promptVersion: "3",
|
|
11462
11559
|
agentId: agent.id,
|
|
11463
11560
|
...input.requestedModel ? { requestedModel: input.requestedModel } : {}
|
|
11464
11561
|
});
|
|
@@ -12557,11 +12654,7 @@ function mergeUpdateInto(fresh, updated) {
|
|
|
12557
12654
|
const source = updated;
|
|
12558
12655
|
for (const field of UPDATE_OWNED_FIELDS) if (field in updated) target[field] = source[field];
|
|
12559
12656
|
else delete target[field];
|
|
12560
|
-
|
|
12561
|
-
const current = fresh.session;
|
|
12562
|
-
for (const field of REVIEWER_SESSION_FIELDS) if (field in fresh.session) session[field] = current[field];
|
|
12563
|
-
else delete session[field];
|
|
12564
|
-
merged.session = session;
|
|
12657
|
+
merged.session = keepReviewerFields(fresh, updated.session);
|
|
12565
12658
|
dropStaleChangeMap(merged);
|
|
12566
12659
|
return merged;
|
|
12567
12660
|
}
|
|
@@ -12991,4 +13084,4 @@ function lineageIds(id) {
|
|
|
12991
13084
|
return [.../* @__PURE__ */ new Set([id, ...lineage.map((review) => review.id)])];
|
|
12992
13085
|
}
|
|
12993
13086
|
//#endregion
|
|
12994
|
-
export { compactQueue as $,
|
|
13087
|
+
export { compactQueue as $, agentById as $n, latestKissRun as $t, createPrState as A, isIssueOutstanding as An, followedBranch as At, toneOf as B, resolveTarget as Bn, phasesFor as Bt, readEvents as C, sectionOf as Cn, claimRequestUrl as Ct, announceJob as D, queueStamp as Dn, fillFileUrlTemplate as Dt, telemetryUploadConsent as E, queueRemove as En, remoteHost as Et, markAllRead as F, processDiscussion as Fn, isTerminal as Ft, extractJsonText as G, resolveModel as Gn, isClaimed as Gt, withUsageRecorded as H, isCommitReview as Hn, purposeOf as Ht, markRead as I, recommendationsOf as In, loadJob as It, readMarker as J, writeAgentPreference as Jn, groupByLineage as Jt, ReviewBeingDeletedError as K, clearAgentPreference as Kn, decideKissRecommendation as Kt, pruneNotifications as L, describeAuthorship as Ln, saveJob as Lt, eventName as M, issuesOutstanding as Mn, allJobs as Mt, headline as N, questionsOutstanding as Nn, endedAt as Nt, branchOf as O, readQueue as On, checkCodeFreshness as Ot, listNotifications as P, reviewerDispositions as Pn, fail as Pt, activateQueued as Q, DEFAULT_AGENT_ID as Qn, kissDecisionsOf as Qt, readNotification as R, WITHHELD_REASON as Rn, PHASES as Rt, startJob as S, parseLifecycle as Sn, writePortPreference as St, recordTelemetryUploadConsent as T, queueAddMany as Tn, forgeFor as Tt, EXPLAIN_SIMPLY_PROMPT as U, git as Un, clearClaim as Ut, unreadCount as V, displayRef as Vn, progressSteps as Vt, asString as W, resolveAgent as Wn, driverGone as Wt, modelHelpLines as X, STORE_ROOT as Xn, indexReviewGroups as Xt, removeWorktree as Y, CONFIG_PATH as Yn, indexKeptIds as Yt, relativeTime as Z, AGENT_IDS as Zn, kissDecisionRefusal as Zt, agentEnvOf as _, isLifecycle as _n, MAX_WORKSPACE_PORT as _t, wasBlocked as a, positionInLineage as an, ensureServer as at, reanalyseReview as b, lifecyclePill as bn, resolveWorkspacePort as bt, RefreshUnavailableError as c, recentWorkspaces as cn, serverEntryExists as ct, refreshPrContext as d, summarise as dn, workspaceUrl as dt, lineageKeyFor as en, agentFor as er, queueForReview as et, isUnchanged as f, touchWorkspace as fn, writeServerRecord as ft, runningJobs as g, activityLabel as gn, DEFAULT_WORKSPACE_PORT as gt, liveUpdateFor as h, LIFECYCLES as hn, feedbackUrl as ht, liveJobsFor as i, mutateWorkspace as in, clearServerRecord as it, createPrUpdate as j, isQuestionOutstanding as jn, reviewedShaOf as jt, subjectOf as k, doneVerb as kn, checkReview as kt, mergeUpdateInto as l, reviewedCommit as ln, spawnServer as lt, UpdateAlreadyRunningError as m, workspaceStamps as mn, PACKAGE_NAME as mt, deleteReview as n, loadWorkspace as nn, AgentCancelledError as nr, readIndexToken as nt, discardJob as o, presentedKissRunOf as on, readServerRecord as ot, askCheckout as p, workspaceRevision as pn, BUILD_VERSION as pt, MANAGED_ROOT as q, readAgentPreference as qn, followedRefName as qt, lineageIds as r, matchingWorkspaceIds as rn, AgentUnavailableError as rr, bootstrapUrl as rt, FETCH_TIMEOUT_MS as s, previousKissResult as sn, reviewsUrl as st, deleteLineage as t, lineagePosition as tn, detectAgents as tr, settleQueue as tt, updateReview as u, reviewedRepositories as un, stopServer as ut, recordKissRun as v, lifecycleAction as vn, MIN_WORKSPACE_PORT as vt, record as w, queueAdd as wn, forgeResolver as wt, runJob as x, offersLifecycle as xn, statedWorkspacePort as xt, startKissJob as y, lifecycleChip as yn, parseWorkspacePort as yt, removeNotification as z, kissOutcome as zn, isLiveJob as zt };
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $
|
|
2
|
+
import { $n as agentById, Bn as resolveTarget, E as telemetryUploadConsent, Ft as isTerminal, Gn as resolveModel, Gt as isClaimed, Ht as purposeOf, It as loadJob, J as readMarker, Jn as writeAgentPreference, Jt as groupByLineage, Mt as allJobs, Qn as DEFAULT_AGENT_ID, Rn as WITHHELD_REASON, Rt as PHASES, S as startJob, St as writePortPreference, T as recordTelemetryUploadConsent, Un as git, Ut as clearClaim, Vn as displayRef, Vt as progressSteps, Wn as resolveAgent, Wt as driverGone, X as modelHelpLines, Xn as STORE_ROOT, Y as removeWorktree, Yn as CONFIG_PATH, Z as relativeTime, Zn as AGENT_IDS, _t as MAX_WORKSPACE_PORT, a as wasBlocked, an as positionInLineage, at as ensureServer, b as reanalyseReview, cn as recentWorkspaces, dn as summarise, dt as workspaceUrl, en as lineageKeyFor, et as queueForReview, g as runningJobs, gt as DEFAULT_WORKSPACE_PORT, h as liveUpdateFor, i as liveJobsFor, in as mutateWorkspace, kt as checkReview, l as mergeUpdateInto, m as UpdateAlreadyRunningError, mt as PACKAGE_NAME, n as deleteReview$1, nn as loadWorkspace, nt as readIndexToken, pt as BUILD_VERSION, q as MANAGED_ROOT, qn as readAgentPreference, qt as followedRefName, rn as matchingWorkspaceIds, rt as bootstrapUrl, st as reviewsUrl, tr as detectAgents, u as updateReview, un as reviewedRepositories, ut as stopServer, v as recordKissRun, vt as MIN_WORKSPACE_PORT, w as record$1, wt as forgeResolver, x as runJob, xt as statedWorkspacePort, yt as parseWorkspacePort, zn as kissOutcome } from "./delete_review-DMJXD3bf.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";
|