prreviewbuddy 0.90.0 → 0.92.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 +58 -0
- package/dist/main.js +14 -2
- package/dist/{mcp_tools-CSj5vcSE.js → mcp_tools-BKPpd9dN.js} +264 -25
- package/dist/server.js +298 -70
- package/package.json +1 -1
- package/static/shell.css +31 -10
- package/static/sidebar.css +198 -6
- package/static/workspace.js +58 -45
|
@@ -4206,6 +4206,18 @@ var REVIEW_ATTENTIONS = [
|
|
|
4206
4206
|
"medium",
|
|
4207
4207
|
"low"
|
|
4208
4208
|
];
|
|
4209
|
+
/** In the order the Issues pane draws them. */
|
|
4210
|
+
var IMPACT_GROUPS = [
|
|
4211
|
+
"failure",
|
|
4212
|
+
"risk",
|
|
4213
|
+
"intent",
|
|
4214
|
+
"maintenance"
|
|
4215
|
+
];
|
|
4216
|
+
var STEP_KINDS = [
|
|
4217
|
+
"verify",
|
|
4218
|
+
"decide",
|
|
4219
|
+
"fix"
|
|
4220
|
+
];
|
|
4209
4221
|
/**
|
|
4210
4222
|
* The JSON in a reply, whether or not the model wrapped it in a fence.
|
|
4211
4223
|
*
|
|
@@ -4373,10 +4385,71 @@ function normalizeIssues(value) {
|
|
|
4373
4385
|
line: typeof item.line === "number" ? item.line : void 0,
|
|
4374
4386
|
sectionId: asSectionId(item),
|
|
4375
4387
|
confidence: REVIEW_ATTENTIONS.includes(item.confidence) ? item.confidence : void 0,
|
|
4376
|
-
existingDiscussion: asClaimedThreadRef(item.existingDiscussion)
|
|
4388
|
+
existingDiscussion: asClaimedThreadRef(item.existingDiscussion),
|
|
4389
|
+
...withConsequence(normalizeConsequence(item.consequence))
|
|
4377
4390
|
};
|
|
4378
4391
|
}).filter((issue) => issue.title.trim() !== "" || issue.description.trim() !== "");
|
|
4379
4392
|
}
|
|
4393
|
+
/**
|
|
4394
|
+
* An issue's consequence, or nothing.
|
|
4395
|
+
*
|
|
4396
|
+
* Well-formedness only. A consequence with no title or no scenario has nothing to say and is
|
|
4397
|
+
* dropped, so the card falls back to its technical account rather than showing an empty headline.
|
|
4398
|
+
* An unknown group is left out rather than defaulted, because every default would be a claim: the
|
|
4399
|
+
* card then sits under "Other issues". A group is never derived from severity or confidence; the
|
|
4400
|
+
* two stay separate attributes, as the model stated them.
|
|
4401
|
+
*/
|
|
4402
|
+
function normalizeConsequence(value) {
|
|
4403
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
4404
|
+
const item = value;
|
|
4405
|
+
const title = asString$1(item.title).trim();
|
|
4406
|
+
const scenario = asString$1(item.scenario).trim();
|
|
4407
|
+
if (!title || !scenario) return void 0;
|
|
4408
|
+
const group = IMPACT_GROUPS.includes(item.group) ? item.group : void 0;
|
|
4409
|
+
const next = normalizeStep(item.next);
|
|
4410
|
+
return {
|
|
4411
|
+
title,
|
|
4412
|
+
scenario,
|
|
4413
|
+
...next ? { next } : {},
|
|
4414
|
+
...group ? { group } : {}
|
|
4415
|
+
};
|
|
4416
|
+
}
|
|
4417
|
+
function normalizeStep(value) {
|
|
4418
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
4419
|
+
const item = value;
|
|
4420
|
+
const text = asString$1(item.text).trim();
|
|
4421
|
+
if (!text) return void 0;
|
|
4422
|
+
return STEP_KINDS.includes(item.kind) ? {
|
|
4423
|
+
kind: item.kind,
|
|
4424
|
+
text
|
|
4425
|
+
} : { text };
|
|
4426
|
+
}
|
|
4427
|
+
/**
|
|
4428
|
+
* A question's scan-first framing, or nothing.
|
|
4429
|
+
*
|
|
4430
|
+
* Well-formedness only, the consequence's rule: a framing with no question or no reason has nothing
|
|
4431
|
+
* to say and is dropped, so the card shows the original question rather than an empty headline.
|
|
4432
|
+
*/
|
|
4433
|
+
function normalizeQuestionFraming(value) {
|
|
4434
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
4435
|
+
const item = value;
|
|
4436
|
+
const question = asString$1(item.question).trim();
|
|
4437
|
+
const why = asString$1(item.why).trim();
|
|
4438
|
+
if (!question || !why) return void 0;
|
|
4439
|
+
const needed = asString$1(item.needed).trim();
|
|
4440
|
+
return {
|
|
4441
|
+
question,
|
|
4442
|
+
why,
|
|
4443
|
+
...needed ? { needed } : {}
|
|
4444
|
+
};
|
|
4445
|
+
}
|
|
4446
|
+
function withFraming(framing) {
|
|
4447
|
+
return framing ? { framing } : {};
|
|
4448
|
+
}
|
|
4449
|
+
/** Spread form, so an issue without one carries no `consequence` key at all. */
|
|
4450
|
+
function withConsequence(consequence) {
|
|
4451
|
+
return consequence ? { consequence } : {};
|
|
4452
|
+
}
|
|
4380
4453
|
function asClaimedThreadRef(value) {
|
|
4381
4454
|
if (typeof value !== "object" || value === null) return void 0;
|
|
4382
4455
|
const claim = value;
|
|
@@ -4403,7 +4476,8 @@ function normalizeQuestions(value) {
|
|
|
4403
4476
|
importance: REVIEW_ATTENTIONS.includes(item.importance) ? item.importance : void 0,
|
|
4404
4477
|
whyThisMatters: typeof item.whyThisMatters === "string" ? item.whyThisMatters : void 0,
|
|
4405
4478
|
file: typeof item.file === "string" ? item.file : void 0,
|
|
4406
|
-
sectionId: asSectionId(item)
|
|
4479
|
+
sectionId: asSectionId(item),
|
|
4480
|
+
...withFraming(normalizeQuestionFraming(item.framing))
|
|
4407
4481
|
};
|
|
4408
4482
|
}).filter((question) => question.question.trim() !== "");
|
|
4409
4483
|
}
|
|
@@ -5693,6 +5767,20 @@ function reviewerDispositions(session) {
|
|
|
5693
5767
|
isStale: (issue) => issue.reconciliationStatus === "affected" && (byId.get(issue.id)?.sessionId ?? session.id) !== session.id
|
|
5694
5768
|
};
|
|
5695
5769
|
}
|
|
5770
|
+
function framableFindings(session) {
|
|
5771
|
+
const dispositions = reviewerDispositions(session);
|
|
5772
|
+
const answered = new Set(session.answeredQuestionIds ?? []);
|
|
5773
|
+
const verdicts = verdictClosure(session);
|
|
5774
|
+
return {
|
|
5775
|
+
issue: (issue) => isIssueOutstanding(issue, dispositions),
|
|
5776
|
+
question: (question) => isQuestionOutstanding(question, answered, verdicts.question)
|
|
5777
|
+
};
|
|
5778
|
+
}
|
|
5779
|
+
/** For a caller with no session: nothing may gain framing. */
|
|
5780
|
+
var NOTHING_FRAMABLE = {
|
|
5781
|
+
issue: () => false,
|
|
5782
|
+
question: () => false
|
|
5783
|
+
};
|
|
5696
5784
|
/**
|
|
5697
5785
|
* An issue is done when the commits fixed it, or when the reviewer dismissed it and that decision
|
|
5698
5786
|
* still stands.
|
|
@@ -12503,6 +12591,76 @@ function applyMotivation(result, candidate, authorDescription) {
|
|
|
12503
12591
|
*/
|
|
12504
12592
|
var SUMMARY_GUIDANCE = `"summary": WHAT the change does, for a reviewer about to read it. Roughly 80-120 words, and fewer for a small change. Name the parts that change and what each now does. Do not explain why the change exists, and do not judge whether it is correct or safe: other fields carry both.`;
|
|
12505
12593
|
//#endregion
|
|
12594
|
+
//#region ../../packages/review-harness/src/domain/ai_review/consequence_guidance.ts
|
|
12595
|
+
/**
|
|
12596
|
+
* What an issue's "consequence" is, as every prompt that raises issues asks for it.
|
|
12597
|
+
*
|
|
12598
|
+
* One fragment and one guidance string, so the first analysis, follow-ups, updates and the
|
|
12599
|
+
* extension's investigation cannot drift apart. The fragment is the whole shape, never an
|
|
12600
|
+
* abbreviation: a model cannot follow a schema it was not shown.
|
|
12601
|
+
*/
|
|
12602
|
+
var CONSEQUENCE_FIELD = "\"consequence\": { \"title\": string, \"scenario\": string, \"group\": \"failure\" | \"risk\" | \"intent\" | \"maintenance\", \"next\"?: { \"kind\": \"verify\" | \"decide\" | \"fix\", \"text\": string } }";
|
|
12603
|
+
/** The same shape on a prior finding's entry in an update, where null withdraws it and absence keeps it. */
|
|
12604
|
+
var CONSEQUENCE_REVISION_FIELD = `${CONSEQUENCE_FIELD.replace("\"consequence\": ", "\"consequence\"?: ")} | null`;
|
|
12605
|
+
var CONSEQUENCE_GUIDANCE = `"consequence" on an issue: the same issue told as what it means, for someone who knows the product but may not know its implementation. It is shown first; "title" and "description" stay the technical account behind it. Reframe around the consequence, do not just simplify the technical wording.
|
|
12606
|
+
- "title": the observable consequence or the meaningful development constraint, as a short sentence (e.g. "Creating a meal can fail halfway, leaving it outside the planner").
|
|
12607
|
+
- "scenario": one or two sentences: the triggering condition and what happens (e.g. "If adding it to the day fails after saving, the user sees an error but the meal still exists. Retrying may then be blocked by its name.").
|
|
12608
|
+
- "next": the one specific step this issue calls for, when there is one. "kind" is "verify" for a test or evidence-gathering step that would settle whether it happens (e.g. "Try a receipt with an unreadable amount."), "decide" for an acceptance, requirement or intent call only the reviewer can make (e.g. "Confirm this broader change is intended."), and "fix" for a concrete corrective action the finding itself supports (e.g. "Update the recovery runbook to name the new restore command."). A fix is not a verification: do not label a remedy "verify". Omit "next" rather than write a generic step or invent a remedy the evidence does not support.
|
|
12609
|
+
- "group", by the consequence and the evidence behind it, never by the kind of file, never by how sure you sound and independently of "severity":
|
|
12610
|
+
- "failure" when the evidence you read establishes an incorrect outcome under a stated condition (e.g. "Saving a meal with no ingredients deletes the existing ones.").
|
|
12611
|
+
- "risk" when a plausible adverse consequence still needs verifying (e.g. "Two people editing the same plan at once may overwrite each other; nothing shows whether saves are serialised."), and say what is unverified.
|
|
12612
|
+
- "intent" when there is a concrete behavioural consequence whose acceptability depends on requirements or intent (e.g. "Rotating the sign-in secret now signs every customer out.").
|
|
12613
|
+
- "maintenance" when it constrains future development, maintainability or reliability and no concrete failure or risk fits better (e.g. "Each new payment provider has to be added in four places that must stay in step.").
|
|
12614
|
+
- Documentation, runbooks, configuration and scripts are classified by what they cause like any code: recovery instructions that restore to the wrong database cause an operational failure when the text establishes it, or a risk when unverified. They are not "maintenance" because they are documentation.
|
|
12615
|
+
- "confidence" is reported separately and does not decide the group. A well-evidenced failure stays a failure at medium confidence; a high severity does not make an unverified risk a failure; a low confidence does not by itself turn a failure into a risk.
|
|
12616
|
+
- Keep every condition and qualification that affects the decision. Avoid code identifiers unless the consequence cannot be understood without one. Do not state severity.
|
|
12617
|
+
- Never claim user harm, a measured performance effect, a reproduction or a certainty the evidence does not give. A performance concern nobody measured says so (e.g. "Opening a meal may do unnecessary work for nested meals... The effect has not been measured."). A maintenance or intent issue is described as one, not as a user-facing failure.
|
|
12618
|
+
- An issue names a concrete consequence. A request for missing requirements with no concrete consequence is a question for the author, not an issue, and is never raised as both.`;
|
|
12619
|
+
/** What "orientation" is for, as the first analysis and an update ask for it. */
|
|
12620
|
+
var ORIENTATION_GUIDANCE = `"orientation": one sentence, at most about 25 words, naming the behaviour or product area this change touches, for a reviewer about to decide on its issues (e.g. "This change affects receipt extraction and how duplicate receipt details are combined."). Say what it touches, not whether it is safe, and do not summarise the issues.`;
|
|
12621
|
+
/**
|
|
12622
|
+
* How an update keeps a prior finding's consequence and resolution true, beside its status.
|
|
12623
|
+
*
|
|
12624
|
+
* The technical text of a prior finding never changes in an update, but what it means can: the
|
|
12625
|
+
* condition it describes may have narrowed, the evidence moved, or the step become moot. A
|
|
12626
|
+
* consequence that no longer describes the finding is worse than none, so the model is shown each
|
|
12627
|
+
* one and must keep, restate or withdraw it.
|
|
12628
|
+
*/
|
|
12629
|
+
var CONSEQUENCE_UPDATE_GUIDANCE = `"consequence" on a finding entry: a finding marked [consequence: ...] has an impact summary the reviewer reads first. Omit "consequence" when it still describes the finding accurately, which is the usual case. Return a restated "consequence" (same shape as on a new issue) when what has changed since alters the condition, the evidence, the next step or the group it describes, most often for an "affected" finding. Return null when it no longer holds and you cannot restate it accurately.
|
|
12630
|
+
A finding marked [consequence: none yet, write one] is still outstanding and has no impact summary: unless you mark it "resolved", return a "consequence" for it, written from the evidence its description already gives together with anything these changes show. Classify it into whichever of the four groups that evidence supports; do not default to "risk", and do not demand fresh proof to keep a failure the existing evidence already establishes. Keep its uncertainty as stated: rewording a finding is not re-verifying it, so never describe it as newly confirmed or tested. Never return "consequence" for a finding with neither marker.
|
|
12631
|
+
"resolvedBehaviour" on a finding entry: only with "resolved", and only when the changed code shows what now happens under the finding's condition, in one sentence for someone who knows the product (e.g. "If adding the meal to the planner fails, the meal is no longer saved."). Omit it when the code does not show that, and whenever the finding is settled by a comment rather than by code.`;
|
|
12632
|
+
/**
|
|
12633
|
+
* The impact summary the reviewer reads first, shown under a prior finding so a later pass can keep,
|
|
12634
|
+
* restate or withdraw it (`CONSEQUENCE_UPDATE_GUIDANCE`, and the investigation's own rule). Group
|
|
12635
|
+
* and step are included: either can go stale on its own. A finding stored without one is marked
|
|
12636
|
+
* as needing one only when the update may add it (`framable`, an outstanding finding); otherwise it
|
|
12637
|
+
* shows nothing, which is what tells the model not to add one.
|
|
12638
|
+
*/
|
|
12639
|
+
function formatPriorConsequence(issue, framable = false) {
|
|
12640
|
+
const consequence = issue.consequence;
|
|
12641
|
+
if (!consequence) return framable ? "\n [consequence: none yet, write one]" : "";
|
|
12642
|
+
const next = consequence.next ? ` Next (${consequence.next.kind ?? "step"}): ${consequence.next.text}` : "";
|
|
12643
|
+
return `\n [consequence: group ${consequence.group ?? "none"}] ${consequence.title.trim().replace(/[.!?]$/, "")}. ${consequence.scenario.trim()}${next}`;
|
|
12644
|
+
}
|
|
12645
|
+
/** A question's scan-first framing, as every prompt that asks questions asks for it. The whole shape. */
|
|
12646
|
+
var QUESTION_FRAMING_FIELD = "\"framing\": { \"question\": string, \"why\": string, \"needed\"?: string }";
|
|
12647
|
+
/** The same shape on a prior question's entry in an update, where null withdraws it and absence keeps it. */
|
|
12648
|
+
var QUESTION_FRAMING_REVISION_FIELD = `${QUESTION_FRAMING_FIELD.replace("\"framing\": ", "\"framing\"?: ")} | null`;
|
|
12649
|
+
var QUESTION_FRAMING_GUIDANCE = `"framing" on a question: the same question, asked so a reviewer who knows the product but not the code can see at a glance what is being asked and why. It is shown first; the original "question" and "whyThisMatters" stay the technical account behind it. It is a presentation of this question, never a second one.
|
|
12650
|
+
- "question": short, at product or operations level (e.g. "Should rotating the sign-in secret require all customers to sign in again?").
|
|
12651
|
+
- "why": one or two sentences on why the answer matters, keeping every condition and uncertainty (e.g. "The current encryption ties stored sessions to that secret."). A conditional premise stays conditional: do not turn "if" into a fact.
|
|
12652
|
+
- "needed": the specific answer or confirmation required, when the question does not already make it plain (e.g. "Confirm whether this consequence is acceptable and documented."). Omit it otherwise.
|
|
12653
|
+
- A question with several parts names every part, so none is lost from view. Do not answer the question in its framing.`;
|
|
12654
|
+
var QUESTION_FRAMING_UPDATE_GUIDANCE = `"framing" on a question entry: a question marked [framing: ...] has a short framing the reviewer reads first. Omit "framing" when it still describes the question accurately. Return a restated "framing" (same shape as on a new question) when these changes alter what is being asked, its condition or what is needed; in particular, when you mark a question "answered" or the changes answer part of it, restate it to name only what is still open, or return null if nothing in it still needs asking. Return null when it no longer holds and you cannot restate it.
|
|
12655
|
+
A question marked [framing: none yet, write one] is still outstanding and has no framing: unless you mark it "answered", return a "framing" for it from what the question and its reasons already say together with anything these changes show, keeping its conditions and uncertainty. Never return "framing" for a question with neither marker.`;
|
|
12656
|
+
/** A prior question's framing, or the marker asking for one, as the update shows it. */
|
|
12657
|
+
function formatPriorFraming(question, framable = false) {
|
|
12658
|
+
const framing = question.framing;
|
|
12659
|
+
if (!framing) return framable ? "\n [framing: none yet, write one]" : "";
|
|
12660
|
+
const needed = framing.needed ? ` Needed: ${framing.needed.trim()}` : "";
|
|
12661
|
+
return `\n [framing] ${framing.question.trim()} ${framing.why.trim()}${needed}`;
|
|
12662
|
+
}
|
|
12663
|
+
//#endregion
|
|
12506
12664
|
//#region ../../packages/review-harness/src/domain/discussion/discussion_delta.ts
|
|
12507
12665
|
/**
|
|
12508
12666
|
* Which collections of a snapshot were capped. A snapshot from before coverage was recorded can
|
|
@@ -13265,6 +13423,7 @@ var STRUCTURED_OUTPUT_INSTRUCTIONS = `In addition to the review principles above
|
|
|
13265
13423
|
"authorQuestion"?: string
|
|
13266
13424
|
},
|
|
13267
13425
|
"overallRisk": "low" | "medium" | "high",
|
|
13426
|
+
"orientation": string,
|
|
13268
13427
|
"sections": [{
|
|
13269
13428
|
"id": string,
|
|
13270
13429
|
"order": number,
|
|
@@ -13279,8 +13438,8 @@ var STRUCTURED_OUTPUT_INSTRUCTIONS = `In addition to the review principles above
|
|
|
13279
13438
|
"reviewWeight": 1 | 2 | 3 | 4 | 5,
|
|
13280
13439
|
"recommendedStartingPoint": boolean
|
|
13281
13440
|
}],
|
|
13282
|
-
"issues": [{ "id": string, "severity": "critical" | "major" | "minor" | "nit", "title": string, "description": string, "file"?: string, "line"?: number, "sectionId"?: string, "confidence"?: "high" | "medium" | "low", "existingDiscussion"?: { "threadId": string, "relation": "same" | "related" } }],
|
|
13283
|
-
"questions": [{ "id": string, "question": string, "importance"?: "high" | "medium" | "low", "whyThisMatters"?: string, "file"?: string, "sectionId"?: string }],
|
|
13441
|
+
"issues": [{ "id": string, "severity": "critical" | "major" | "minor" | "nit", "title": string, "description": string, "file"?: string, "line"?: number, "sectionId"?: string, "confidence"?: "high" | "medium" | "low", ${CONSEQUENCE_FIELD}, "existingDiscussion"?: { "threadId": string, "relation": "same" | "related" } }],
|
|
13442
|
+
"questions": [{ "id": string, "question": string, "importance"?: "high" | "medium" | "low", "whyThisMatters"?: string, ${QUESTION_FRAMING_FIELD}, "file"?: string, "sectionId"?: string }],
|
|
13284
13443
|
"recommendation": string,
|
|
13285
13444
|
"nextSteps": string[]
|
|
13286
13445
|
}
|
|
@@ -13299,6 +13458,9 @@ Field guidance:
|
|
|
13299
13458
|
- "recommendation": a 1-2 sentence merge verdict aimed at the developer (e.g. "Approve" or "Request changes — fix the unhandled rejection before merging"). Do not just restate the risk level, and do not copy Guide section content verbatim into this field.
|
|
13300
13459
|
- "nextSteps": concrete actions to take before merging (specific tests to run, files to double-check), not a restatement of the Guide.
|
|
13301
13460
|
- "issues": report only issues worth the reviewer's attention — do not invent issues to fill out the array, and do not omit significant issues. Let the count reflect the actual PR (a trivial PR may have zero or one issue; a large or risky PR may have several).
|
|
13461
|
+
- ${CONSEQUENCE_GUIDANCE}
|
|
13462
|
+
- ${QUESTION_FRAMING_GUIDANCE}
|
|
13463
|
+
- ${ORIENTATION_GUIDANCE}
|
|
13302
13464
|
- "existingDiscussion" on an issue: set this only when a thread in the PR DISCUSSION CONTEXT block already raises this same concern, and you have independently confirmed from the diff that it still applies. "threadId" must be copied verbatim from that thread's [T_...] marker — never invent an id, never guess, and omit the field entirely if no thread matches. Set "relation" to "same" when the thread already makes this exact point, or "related" when it discusses this area without covering the finding — a reviewer acts differently on "someone said this already" than on "someone was looking near here". Still write the issue normally; this field only records that the point was raised before, so the reviewer is not shown it as a fresh discovery. Do not use it to pad the review with issues you would otherwise have left out.
|
|
13303
13465
|
- "confidence" on an issue: how sure you are the issue is real, on the same high/medium/low scale as a question's "importance". This is a separate axis from "severity", which is how much it would matter if real — a critical issue you are unsure about and a nit you are certain of are different things to act on, so do not let one field stand in for the other. Use LOW when you are reasoning from a diff excerpt without the surrounding code, and say what would confirm it in the description. Omit the field rather than guessing a middle value.
|
|
13304
13466
|
- "questions": each one is a genuine open item the reviewer needs answered before they can sign off, not a rhetorical prompt. "importance" is how much attention it deserves, on the same high/medium/low scale as a section's "reviewAttention" (e.g. a question about a possibly-exposed secret is "high"; a naming preference is "low"). "whyThisMatters" is 1-2 sentences explaining the concrete consequence of the question going unanswered — not a restatement of the question itself.
|
|
@@ -13356,6 +13518,7 @@ function parseUnchecked(raw) {
|
|
|
13356
13518
|
schemaVersion: 1,
|
|
13357
13519
|
summary,
|
|
13358
13520
|
overallRisk: RISKS.includes(obj.overallRisk) ? obj.overallRisk : "medium",
|
|
13521
|
+
...asString$1(obj.orientation).trim() ? { orientation: asString$1(obj.orientation).trim() } : {},
|
|
13359
13522
|
sections: normalizeSections(obj.sections),
|
|
13360
13523
|
issues: normalizeIssues(obj.issues),
|
|
13361
13524
|
questions: normalizeQuestions(obj.questions),
|
|
@@ -17995,13 +18158,13 @@ function priorFindingVerdict(issue, flag) {
|
|
|
17995
18158
|
* reviewer may have moved it, and a model told only the analysis's grade would re-judge from where
|
|
17996
18159
|
* the review no longer stands. A caller with no ledger passes `ANALYSIS_ONLY`.
|
|
17997
18160
|
*/
|
|
17998
|
-
function formatPriorFindings(issues, assess, reassess = /* @__PURE__ */ new Map(), status = NO_STATUS) {
|
|
18161
|
+
function formatPriorFindings(issues, assess, reassess = /* @__PURE__ */ new Map(), status = NO_STATUS, framable = NOTHING_FRAMABLE) {
|
|
17999
18162
|
if (!issues.length) return "(The previous analysis raised no issues.)";
|
|
18000
18163
|
return issues.map((issue, index) => {
|
|
18001
18164
|
const related = (issue.relatedFiles ?? []).map((file) => ` [related: ${file}, not changed]`).join("");
|
|
18002
18165
|
const location = (issue.file ? ` [${issue.file}${issue.line ? `:${issue.line}` : ""}]` : "") + related;
|
|
18003
18166
|
const description = issue.description.trim();
|
|
18004
|
-
return `${index}. (${promptGrade(assess("issue", issue))})${location}${priorFindingVerdict(issue, reassess.get(index))}${acceptedVerdict(status("issue", issue.id))} ${issue.title.trim()}${description ? `\n ${description}` : ""}`;
|
|
18167
|
+
return `${index}. (${promptGrade(assess("issue", issue))})${location}${priorFindingVerdict(issue, reassess.get(index))}${acceptedVerdict(status("issue", issue.id))} ${issue.title.trim()}${description ? `\n ${description}` : ""}${formatPriorConsequence(issue, framable.issue(issue))}`;
|
|
18005
18168
|
}).join("\n");
|
|
18006
18169
|
}
|
|
18007
18170
|
/**
|
|
@@ -18010,10 +18173,10 @@ function formatPriorFindings(issues, assess, reassess = /* @__PURE__ */ new Map(
|
|
|
18010
18173
|
* of the issue shape returned issues with no severity, no file and in some cases no content.
|
|
18011
18174
|
* Keep in step with STRUCTURED_OUTPUT_INSTRUCTIONS in pipeline.ts.
|
|
18012
18175
|
*/
|
|
18013
|
-
var QUESTION_SHAPE_LINE =
|
|
18176
|
+
var QUESTION_SHAPE_LINE = ` "questions": [{ "sourceIndex": number, "status": "answered" | "still-open" | "affected", "answer"?: string, "note"?: string, ${QUESTION_FRAMING_REVISION_FIELD}, "importance"?: "high" | "medium" | "low", "importanceReason"?: string }],`;
|
|
18014
18177
|
var RECONCILIATION_SHAPE = `{
|
|
18015
|
-
"findings": [{ "sourceIndex": number, "status": "resolved" | "still-open" | "affected", "note"?: string, "severity"?: "critical" | "major" | "minor" | "nit", "severityReason"?: string }],
|
|
18016
|
-
"newIssues": [{ "id": string, "severity": "critical" | "major" | "minor" | "nit", "title": string, "description": string, "file"?: string, "line"?: number, "confidence"?: "high" | "medium" | "low" }],
|
|
18178
|
+
"findings": [{ "sourceIndex": number, "status": "resolved" | "still-open" | "affected", "note"?: string, ${CONSEQUENCE_REVISION_FIELD}, "resolvedBehaviour"?: string, "severity"?: "critical" | "major" | "minor" | "nit", "severityReason"?: string }],
|
|
18179
|
+
"newIssues": [{ "id": string, "severity": "critical" | "major" | "minor" | "nit", "title": string, "description": string, "file"?: string, "line"?: number, ${CONSEQUENCE_FIELD}, "confidence"?: "high" | "medium" | "low" }],
|
|
18017
18180
|
"newSections": [{
|
|
18018
18181
|
"id": string,
|
|
18019
18182
|
"order": number,
|
|
@@ -18028,6 +18191,7 @@ var RECONCILIATION_SHAPE = `{
|
|
|
18028
18191
|
"reviewWeight": 1 | 2 | 3 | 4 | 5
|
|
18029
18192
|
}],
|
|
18030
18193
|
"summary": string,
|
|
18194
|
+
"orientation": string,
|
|
18031
18195
|
"overallRisk": "low" | "medium" | "high",
|
|
18032
18196
|
"recommendation": string,
|
|
18033
18197
|
"nextSteps": string[]
|
|
@@ -18055,7 +18219,7 @@ function reconciliationShape(includeQuestions, withDiscussion = false) {
|
|
|
18055
18219
|
* question's own id is withheld so it cannot be echoed back in place of an index, and enough
|
|
18056
18220
|
* context travels for a judgement without inviting a rewrite of the question itself.
|
|
18057
18221
|
*/
|
|
18058
|
-
function formatPriorQuestions(questions, assess, status = NO_STATUS) {
|
|
18222
|
+
function formatPriorQuestions(questions, assess, status = NO_STATUS, framable = NOTHING_FRAMABLE) {
|
|
18059
18223
|
if (!questions.length) return "(The previous analysis raised no questions.)";
|
|
18060
18224
|
return questions.map((question, index) => {
|
|
18061
18225
|
const related = (question.relatedFiles ?? []).map((file) => ` [related: ${file}, not changed]`).join("");
|
|
@@ -18064,7 +18228,7 @@ function formatPriorQuestions(questions, assess, status = NO_STATUS) {
|
|
|
18064
18228
|
const verdict = alreadyAnswered(question) ? " [previously: answered]" : priorVerdict(question);
|
|
18065
18229
|
const assessment = assess("question", question);
|
|
18066
18230
|
const importance = assessment.current ? ` [importance: ${promptGrade(assessment)}]` : "";
|
|
18067
|
-
return `${index}.${location}${verdict}${acceptedVerdict(status("question", question.id))}${importance} ${question.question.trim()}${why ? `\n ${why}` : ""}`;
|
|
18231
|
+
return `${index}.${location}${verdict}${acceptedVerdict(status("question", question.id))}${importance} ${question.question.trim()}${why ? `\n ${why}` : ""}${formatPriorFraming(question, framable.question(question))}`;
|
|
18068
18232
|
}).join("\n");
|
|
18069
18233
|
}
|
|
18070
18234
|
/**
|
|
@@ -18145,7 +18309,7 @@ function buildReconciliationInstructions(input, options = {}) {
|
|
|
18145
18309
|
const discussion = options.discussion;
|
|
18146
18310
|
const conversationOnly = discussion !== void 0 && !discussion.codeChanged;
|
|
18147
18311
|
const truncationWarning = possiblyTruncated ? `\n\nIMPORTANT: the list of changes above is INCOMPLETE — more files changed than could be retrieved. Do not mark a previous finding "resolved" on the strength of absence: a file you cannot see may or may not contain the fix. Prefer "still-open" or "affected" where you cannot see the relevant code, and say so in the note.` : "";
|
|
18148
|
-
const questionList = includeQuestions ? `\n\nPrevious open questions, numbered — refer to each by its number in "sourceIndex":\n${formatPriorQuestions(previous.questions, input.assess, input.status)}` : "";
|
|
18312
|
+
const questionList = includeQuestions ? `\n\nPrevious open questions, numbered — refer to each by its number in "sourceIndex":\n${formatPriorQuestions(previous.questions, input.assess, input.status, input.framable)}` : "";
|
|
18149
18313
|
const tasks = [
|
|
18150
18314
|
`${discussion ? `For EVERY numbered finding above, decide what ${conversationOnly ? "the changes in the conversation" : "the new commits and the changes in the conversation"} did to it:
|
|
18151
18315
|
- "resolved": ${conversationOnly ? "" : "the new commits fix it, and you can point at the change that does so; or "}the conversation gives evidence that invalidates its premise, under the rules below.
|
|
@@ -18168,7 +18332,7 @@ ${REASSESS_TASK}` : ""}
|
|
|
18168
18332
|
${GRADE_TASK.question}`] : [],
|
|
18169
18333
|
conversationOnly ? `No commits were pushed, so there is no new code to review. Report a problem in "newIssues" only where the conversation points at something in the code the earlier analysis missed and you have confirmed it by reading the code. Do NOT repeat a previous finding here: if it still stands, that is what "still-open" is for.` : `Read the changed code above as a reviewer, not only as an auditor of the numbered list. These commits have not been reviewed by anyone. Report every genuinely NEW problem you find in them in "newIssues", whether or not it relates to anything on the list — code written to fix a finding is exactly where a regression gets introduced, and reassessing the list and stopping there is half the job. Do NOT repeat a previous finding here: if it still stands, that is what "still-open" is for.`,
|
|
18170
18334
|
`If the new changes introduce an area the earlier analysis had no section for, add it to "newSections". Otherwise return an empty array. Do not restate or restructure the earlier analysis's existing sections.`,
|
|
18171
|
-
`Give a fresh "summary", "overallRisk", "recommendation" and "nextSteps" for the pull request AS IT NOW STANDS, taking both the earlier findings that survive and the new changes into account. Unlike a partial review, you have been shown the earlier analysis in full and are expected to revise its verdict where the new changes justify it. ${SUMMARY_GUIDANCE}`
|
|
18335
|
+
`Give a fresh "summary", "overallRisk", "recommendation" and "nextSteps" for the pull request AS IT NOW STANDS, taking both the earlier findings that survive and the new changes into account. Unlike a partial review, you have been shown the earlier analysis in full and are expected to revise its verdict where the new changes justify it. ${SUMMARY_GUIDANCE} ${ORIENTATION_GUIDANCE}`
|
|
18172
18336
|
].map((task, index) => `${index + 1}. ${task}`).join("\n");
|
|
18173
18337
|
return `${conversationOnly ? `You are RECONCILING an earlier analysis of this pull request against what has changed in its conversation since that analysis was made.
|
|
18174
18338
|
|
|
@@ -18183,7 +18347,7 @@ Overall risk: ${previous.overallRisk}
|
|
|
18183
18347
|
Recommendation: ${previous.recommendation}
|
|
18184
18348
|
|
|
18185
18349
|
Previous findings, numbered — refer to each by its number in "sourceIndex":
|
|
18186
|
-
${formatPriorFindings(previous.issues, input.assess, reassess, input.status)}${questionList}${truncationWarning}
|
|
18350
|
+
${formatPriorFindings(previous.issues, input.assess, reassess, input.status, input.framable)}${questionList}${truncationWarning}
|
|
18187
18351
|
${discussion ? `\n${DISCUSSION_RULES}\n` : ""}
|
|
18188
18352
|
YOUR TASK
|
|
18189
18353
|
|
|
@@ -18194,6 +18358,10 @@ ${reconciliationShape(includeQuestions, discussion !== void 0)}
|
|
|
18194
18358
|
|
|
18195
18359
|
"note" is one short sentence on *why* the status is what it is — name the change that resolved it, or what leaves it standing.${discussion ? " Where a comment is the reason, name its author." : ""} Omit it rather than restating the finding.
|
|
18196
18360
|
|
|
18361
|
+
${CONSEQUENCE_UPDATE_GUIDANCE}
|
|
18362
|
+
|
|
18363
|
+
${CONSEQUENCE_GUIDANCE}
|
|
18364
|
+
${includeQuestions ? `\n${QUESTION_FRAMING_UPDATE_GUIDANCE}\n\n${QUESTION_FRAMING_GUIDANCE}\n` : ""}
|
|
18197
18365
|
"severity" on a new issue is how much it would matter if real; "confidence" is how sure you are that it is real. Separate axes — do not let one stand in for the other, and omit "confidence" rather than guessing a middle. Report only what is worth the reviewer's attention: empty arrays are valid answers and are far better than padded ones.`;
|
|
18198
18366
|
}
|
|
18199
18367
|
/**
|
|
@@ -18312,10 +18480,14 @@ function parseReconciliationResult(raw, priorCount, options = {}) {
|
|
|
18312
18480
|
const note = asString$1(item.note).trim();
|
|
18313
18481
|
const grade = parseGrade("issue", item.severity, item.severityReason);
|
|
18314
18482
|
const cites = parseCitation(item.evidence);
|
|
18483
|
+
const resolvedBehaviour = asString$1(item.resolvedBehaviour).trim();
|
|
18484
|
+
const consequence = item.consequence === null ? null : normalizeConsequence(item.consequence);
|
|
18315
18485
|
findings.push({
|
|
18316
18486
|
sourceIndex,
|
|
18317
18487
|
status,
|
|
18318
18488
|
...note ? { note } : {},
|
|
18489
|
+
...consequence !== void 0 ? { consequence } : {},
|
|
18490
|
+
...resolvedBehaviour && status === "resolved" ? { resolvedBehaviour } : {},
|
|
18319
18491
|
...grade ? { grade: {
|
|
18320
18492
|
to: grade.to,
|
|
18321
18493
|
reason: grade.reason
|
|
@@ -18333,6 +18505,7 @@ function parseReconciliationResult(raw, priorCount, options = {}) {
|
|
|
18333
18505
|
recommendedStartingPoint: false
|
|
18334
18506
|
})),
|
|
18335
18507
|
summary: asString$1(obj.summary).trim(),
|
|
18508
|
+
orientation: asString$1(obj.orientation).trim(),
|
|
18336
18509
|
overallRisk: RISKS.includes(obj.overallRisk) ? obj.overallRisk : null,
|
|
18337
18510
|
recommendation: asString$1(obj.recommendation).trim(),
|
|
18338
18511
|
nextSteps: asStringArray(obj.nextSteps)
|
|
@@ -18350,15 +18523,16 @@ function parseReconciliationResult(raw, priorCount, options = {}) {
|
|
|
18350
18523
|
* Every prior finding therefore survives into the new result, in its original order, carrying its
|
|
18351
18524
|
* original id, severity and text. Only the status is added.
|
|
18352
18525
|
*/
|
|
18353
|
-
function reconcileIssues(prior, findings, record) {
|
|
18526
|
+
function reconcileIssues(prior, findings, record, framable = NOTHING_FRAMABLE) {
|
|
18354
18527
|
const byIndex = new Map(findings.map((f) => [f.sourceIndex, f]));
|
|
18355
18528
|
return prior.map((issue, index) => {
|
|
18356
18529
|
const verdict = byIndex.get(index);
|
|
18357
18530
|
const flag = issue.reconciliationStatus === "resolved" ? record?.flags?.get(index) : void 0;
|
|
18358
18531
|
if (flag && record) {
|
|
18359
18532
|
const entry = reassessedEntry(verdict, flag, record);
|
|
18533
|
+
const { resolvedBehaviour: _reopened, ...reassessed } = withRevisedConsequence(issue, verdict, false);
|
|
18360
18534
|
return {
|
|
18361
|
-
...
|
|
18535
|
+
...reassessed,
|
|
18362
18536
|
reconciliationStatus: entry.status,
|
|
18363
18537
|
...entry.reason ? { reconciliationNote: entry.reason } : {},
|
|
18364
18538
|
statusHistory: appendStatusChange(issue, entry),
|
|
@@ -18368,16 +18542,56 @@ function reconcileIssues(prior, findings, record) {
|
|
|
18368
18542
|
if (issue.reconciliationStatus === "resolved") return issue;
|
|
18369
18543
|
const status = verdict?.status ?? "still-open";
|
|
18370
18544
|
const recorded = record && isStatusChange(issue.reconciliationStatus, status) ? { statusHistory: appendStatusChange(issue, changeEntry(status, verdict, record)) } : {};
|
|
18545
|
+
const fixedInCode = status === "resolved" && !verdict?.evidence && record?.basis !== "conversation";
|
|
18546
|
+
const { resolvedBehaviour: _previous, ...current } = withRevisedConsequence(issue, verdict, status !== "resolved" && framable.issue(issue));
|
|
18371
18547
|
return {
|
|
18372
|
-
...issue,
|
|
18548
|
+
...withNote(current, verdict?.note, isStatusChange(issue.reconciliationStatus, status)),
|
|
18549
|
+
...fixedInCode && verdict?.resolvedBehaviour ? { resolvedBehaviour: verdict.resolvedBehaviour } : {},
|
|
18373
18550
|
reconciliationStatus: status,
|
|
18374
|
-
...verdict?.note ? { reconciliationNote: verdict.note } : {},
|
|
18375
18551
|
...recorded,
|
|
18376
18552
|
...record?.against ? { reconciledAgainst: verdict?.evidence ? "conversation" : record.against } : {}
|
|
18377
18553
|
};
|
|
18378
18554
|
});
|
|
18379
18555
|
}
|
|
18380
18556
|
/**
|
|
18557
|
+
* The finding with the note this round gave, or the one it had. A note argues for the status it was
|
|
18558
|
+
* written with, so silence keeps it only while that status holds: one this round changed leaves it
|
|
18559
|
+
* behind, where it would contradict the new status on the card.
|
|
18560
|
+
*/
|
|
18561
|
+
function withNote(finding, note, statusChanged) {
|
|
18562
|
+
if (note) return {
|
|
18563
|
+
...finding,
|
|
18564
|
+
reconciliationNote: note
|
|
18565
|
+
};
|
|
18566
|
+
if (!statusChanged) return finding;
|
|
18567
|
+
const { reconciliationNote: _superseded, ...rest } = finding;
|
|
18568
|
+
return rest;
|
|
18569
|
+
}
|
|
18570
|
+
/**
|
|
18571
|
+
* The issue with its consequence kept, restated, withdrawn or added, as the update said.
|
|
18572
|
+
*
|
|
18573
|
+
* Silence keeps it: the model was shown it and asked to change it only where it no longer holds.
|
|
18574
|
+
* An issue stored without one gains the one offered only when `mayFrame`: it is still outstanding
|
|
18575
|
+
* after this update, so the card the reviewer is about to work from becomes scan-first. A resolved,
|
|
18576
|
+
* dismissed or verdict-closed issue is never given presentation it was not written with, and a
|
|
18577
|
+
* `null` for an issue that has nothing to withdraw changes nothing.
|
|
18578
|
+
*/
|
|
18579
|
+
function withRevisedConsequence(issue, verdict, mayFrame) {
|
|
18580
|
+
if (verdict?.consequence === void 0) return issue;
|
|
18581
|
+
if (!issue.consequence) return mayFrame && verdict.consequence ? {
|
|
18582
|
+
...issue,
|
|
18583
|
+
consequence: verdict.consequence
|
|
18584
|
+
} : issue;
|
|
18585
|
+
if (verdict.consequence === null) {
|
|
18586
|
+
const { consequence: _withdrawn, ...rest } = issue;
|
|
18587
|
+
return rest;
|
|
18588
|
+
}
|
|
18589
|
+
return {
|
|
18590
|
+
...issue,
|
|
18591
|
+
consequence: verdict.consequence
|
|
18592
|
+
};
|
|
18593
|
+
}
|
|
18594
|
+
/**
|
|
18381
18595
|
* The same defences the findings get, applied to questions.
|
|
18382
18596
|
*
|
|
18383
18597
|
* Out-of-range and duplicate indices are dropped rather than allowed to throw, and the first answer
|
|
@@ -18400,10 +18614,12 @@ function parseQuestions(value, priorCount) {
|
|
|
18400
18614
|
const note = asString$1(item.note).trim();
|
|
18401
18615
|
const answer = asString$1(item.answer).trim();
|
|
18402
18616
|
const grade = parseGrade("question", item.importance, item.importanceReason);
|
|
18617
|
+
const framing = item.framing === null ? null : normalizeQuestionFraming(item.framing);
|
|
18403
18618
|
questions.push({
|
|
18404
18619
|
sourceIndex,
|
|
18405
18620
|
status,
|
|
18406
18621
|
...note ? { note } : {},
|
|
18622
|
+
...framing !== void 0 ? { framing } : {},
|
|
18407
18623
|
...status === "answered" && answer ? { answer } : {},
|
|
18408
18624
|
...grade ? { grade: {
|
|
18409
18625
|
to: grade.to,
|
|
@@ -18438,7 +18654,7 @@ function parseQuestions(value, priorCount) {
|
|
|
18438
18654
|
function alreadyAnswered(question) {
|
|
18439
18655
|
return question.reconciliationStatus === "answered" || question.reconciliationAnswer !== void 0;
|
|
18440
18656
|
}
|
|
18441
|
-
function reconcileQuestions(prior, reconciled, against) {
|
|
18657
|
+
function reconcileQuestions(prior, reconciled, against, framable = NOTHING_FRAMABLE) {
|
|
18442
18658
|
const recorded = against ? { reconciledAgainst: against } : {};
|
|
18443
18659
|
const byIndex = new Map(reconciled.map((entry) => [entry.sourceIndex, entry]));
|
|
18444
18660
|
return prior.map((question, index) => {
|
|
@@ -18454,15 +18670,35 @@ function reconcileQuestions(prior, reconciled, against) {
|
|
|
18454
18670
|
};
|
|
18455
18671
|
const answered = verdict.status === "answered" && verdict.answer !== void 0;
|
|
18456
18672
|
const status = verdict.status !== "answered" ? verdict.status : answered ? "answered" : "affected";
|
|
18673
|
+
const changed = (question.reconciliationStatus ?? "still-open") !== status;
|
|
18457
18674
|
return {
|
|
18458
|
-
...question,
|
|
18675
|
+
...withNote(withRevisedFraming(question, verdict, status !== "answered" && framable.question(question)), verdict.note, changed),
|
|
18459
18676
|
reconciliationStatus: status,
|
|
18460
|
-
...verdict.note ? { reconciliationNote: verdict.note } : {},
|
|
18461
18677
|
...answered ? { reconciliationAnswer: verdict.answer } : {},
|
|
18462
18678
|
...recorded
|
|
18463
18679
|
};
|
|
18464
18680
|
});
|
|
18465
18681
|
}
|
|
18682
|
+
/**
|
|
18683
|
+
* The question with its framing kept, restated, withdrawn or added: `withRevisedConsequence`'s rule.
|
|
18684
|
+
* A framed question is revised whatever its new status, because an answer is exactly what can make
|
|
18685
|
+
* its "needed" line stale; an unframed one gains a framing only while it is still outstanding.
|
|
18686
|
+
*/
|
|
18687
|
+
function withRevisedFraming(question, verdict, mayFrame) {
|
|
18688
|
+
if (verdict.framing === void 0) return question;
|
|
18689
|
+
if (!question.framing) return mayFrame && verdict.framing ? {
|
|
18690
|
+
...question,
|
|
18691
|
+
framing: verdict.framing
|
|
18692
|
+
} : question;
|
|
18693
|
+
if (verdict.framing === null) {
|
|
18694
|
+
const { framing: _withdrawn, ...rest } = question;
|
|
18695
|
+
return rest;
|
|
18696
|
+
}
|
|
18697
|
+
return {
|
|
18698
|
+
...question,
|
|
18699
|
+
framing: verdict.framing
|
|
18700
|
+
};
|
|
18701
|
+
}
|
|
18466
18702
|
/** Marks a reconciliation's own findings as new, so the UI can tell them from carried-forward ones. */
|
|
18467
18703
|
function markNewIssues(issues, against) {
|
|
18468
18704
|
return issues.map((issue) => ({
|
|
@@ -18565,12 +18801,13 @@ function applyReconciliation(previous, parsed, context) {
|
|
|
18565
18801
|
basis: context.codeChanged ? "code" : "conversation",
|
|
18566
18802
|
flags,
|
|
18567
18803
|
against
|
|
18568
|
-
}), ...markNewIssues(parsed.newIssues, against)];
|
|
18569
|
-
const questions = reconcileQuestions(previous.questions, parsed.questions, against);
|
|
18804
|
+
}, context.framable), ...markNewIssues(parsed.newIssues, against)];
|
|
18805
|
+
const questions = reconcileQuestions(previous.questions, parsed.questions, against, context.framable);
|
|
18570
18806
|
const { motivation } = context;
|
|
18571
18807
|
const composed = {
|
|
18572
18808
|
schemaVersion: 1,
|
|
18573
18809
|
summary: parsed.summary || previous.summary,
|
|
18810
|
+
...parsed.orientation || previous.orientation ? { orientation: parsed.orientation || previous.orientation } : {},
|
|
18574
18811
|
...motivation ? { motivation } : {},
|
|
18575
18812
|
overallRisk: parsed.overallRisk ?? previous.overallRisk,
|
|
18576
18813
|
recommendation: parsed.recommendation || previous.recommendation,
|
|
@@ -19005,7 +19242,8 @@ async function reconcile(workspace, runners, reviewedSha, remote, conversationOk
|
|
|
19005
19242
|
codeChanged: delta !== null,
|
|
19006
19243
|
conversation: prepared,
|
|
19007
19244
|
assess: assessmentLookup(workspace.session),
|
|
19008
|
-
motivation
|
|
19245
|
+
motivation,
|
|
19246
|
+
framable: framableFindings(workspace.session)
|
|
19009
19247
|
});
|
|
19010
19248
|
signal.throwIfAborted();
|
|
19011
19249
|
cancellers.delete(jobId);
|
|
@@ -19514,6 +19752,7 @@ ${buildReconciliationInstructions({
|
|
|
19514
19752
|
previous,
|
|
19515
19753
|
assess: assessmentLookup(workspace.session),
|
|
19516
19754
|
status: statusLookup(workspace.session),
|
|
19755
|
+
framable: framableFindings(workspace.session),
|
|
19517
19756
|
fromSha: reviewedSha,
|
|
19518
19757
|
toSha: newHead,
|
|
19519
19758
|
totalCommits: commits,
|
|
@@ -21233,4 +21472,4 @@ var MCP_TOOL_NAMES = [
|
|
|
21233
21472
|
"ask_buddy"
|
|
21234
21473
|
];
|
|
21235
21474
|
//#endregion
|
|
21236
|
-
export { readAskRequest as $,
|
|
21475
|
+
export { readAskRequest as $, runnableAgents as $a, explanationOf as $i, authorPreview as $n, kissDecisionsOf as $r, recordRuntimeBestEffort as $t, settleQueue as A, TargetError as Aa, createWithMembers as Ai, moveIds as An, attemptIdOf as Ar, UpdateAlreadyRunningError as At, humanizeModelId as B, agentIdOf as Ba, queueStamp as Bi, existingPaths as Bn, phasesFor as Br, append as Bt, parsePullRequestLink as C, objectWithAnyOf as Ca, lifecyclePillAction as Ci, createPrState as Cn, followedBranch as Cr, RefreshUnavailableError as Ct, activateQueued as D, resolveTarget as Da, sectionOf as Di, markAllRead as Dn, fillFileUrlTemplate as Dr, parkedUpdateRefusal as Dt, relativeTime as E, kissOutcome as Ea, parseLifecycle as Ei, listNotifications as En, forgeResolver as Er, mergeUpdateInto as Et, spawnRunner as F, shorthandOf as Fa, setMembership as Fi, retireNotification as Fn, pruneJobResidue as Fr, prepareReview as Ft, reviewTag as G, STORE_ROOT as Ga, issuesOutstanding as Gi, storedConversation as Gn, isClaimed as Gr, recordTelemetryUploadConsent as Gt, findingRef as H, readAgentPreference as Ha, doneVerb as Hi, adoptLegacyBaseline as Hn, purposeOf as Hr, record as Ht, applyUpdate as I, git as Ia, updateCollections as Ii, toneOf as In, saveJob as Ir, settleReview as It, forgetAskRequest as J, agentFor as Ja, reviewerDispositions as Ji, isUnchanged as Jn, followedRefName as Jr, BUILD_VERSION as Jt, reviewTagsIn as K, AGENT_IDS as Ka, questionsOutstanding as Ki, unforeseenFailure as Kn, CLAIM_LEASE_MS as Kr, telemetryUploadConsent as Kt, modelProvenanceOf as L, refExists as La, queueAdd as Li, unreadAround as Ln, PHASES as Lr, reanalyseReview as Lt, RUNNER_MARKER as M, resolveBase as Ma, nameProblemText as Mi, readNotification as Mn, fail as Mr, runningJobs as Mt, cliEntry as N, AmbiguousRefError as Na, readCollections as Ni, readStateOf as Nn, isTerminal as Nr, failureOf as Nt, compactQueue as O, originRemote as Oa, collectionsStamp as Oi, markRead as On, RUN_RECORD_RETENTION_MS as Or, updateReview as Ot, runDetached as P, shortNameOf as Pa, renameCollection as Pi, removeNotification as Pn, loadJob as Pr, observeReview as Pt, markAskRunning as Q, parkedReason as Qa, explanationActionOf as Qi, UNESTABLISHED_MOTIVATION as Qn, kissDecisionRefusal as Qr, mapRuntimes as Qt, provenanceDetailLines as R, resolveAgent as Ra, queueAddMany as Ri, unreadCount as Rn, isLiveJob as Rr, runJob as Rt, extractPullRequestLinks as S, extractJsonText as Sa, lifecycleName as Si, createArchitectureNotification as Sn, checkReview as Sr, FETCH_TIMEOUT_MS as St, runBatch as T, WITHHELD_REASON as Ta, offersLifecycle as Ti, eventName as Tn, fetchHead as Tr, cancellableHere as Tt, findingRefs as U, writeAgentPreference as Ua, isIssueOutstanding as Ui, prepareConversationWithin as Un, clearClaim as Ur, stamp as Ut, findingAtRef as V, clearAgentPreference as Va, readQueue as Vi, ASK_REREAD_CEILING_MS as Vn, progressSteps as Vr, readEvents as Vt, refOf as W, CONFIG_PATH as Wa, isQuestionOutstanding as Wi, saveRefresh as Wn, driverGone as Wr, deliver as Wt, isRequestId as X, detectAgents as Xa, processDiscussion as Xi, EXPLAIN_SIMPLY_PROMPT as Xn, indexKeptIds as Xr, feedbackUrl as Xt, interruption as Y, agentIdentityOf as Ya, verdictClosure as Yi, agentEnvOf as Yn, groupByLineage as Yr, PACKAGE_NAME as Yt, isTerminalAsk as Z, isAgentId as Za, recommendationsOf as Zi, chatConversationSection as Zn, indexReviewGroups as Zr, waitingHistory as Zt, endRun as _, statusLookup as _a, activityAttributes as _i, writeJsonAtomically as _n, requestJobStop as _r, parseWorkspacePort as _t, lineageIds as a, assessmentLookup as aa, mutateWorkspace as ai, loadArchitecture as an, escapeHtml as ar, healthyPort as at, stopRun as b, SEVERITIES as ba, lifecycleChip as bi, subjectOf as bn, findExistingReview as br, writePortPreference as bt, discardJob as c, findingAssessment as ca, previousKissResult as ci, repositoryKey as cn, ReviewBeingDeletedError as cr, serverEntryExists as ct, startKissJob as d, gradeScale as da, reviewedRepositories as di, trackedFiles as dn, MANAGED_ROOT as dr, stopServer as dt, isExplanationAction as ea, latestKissRun as ei, RUNTIME_WORDS as en, versionFrom as eo, hasAuthorContent as er, recordAskAccepted as et, isDriving as f, isGradeFor as fa, summarise as fi, ownersOf as fn, createWorktree as fr, workspaceUrl as ft, completeRun as g, sourcePhrase as ga, LIFECYCLES as gi, isArchitectureId as gn, removeWorktree as gr, MIN_WORKSPACE_PORT as gt, beginRun as h, reassessIn as ha, workspaceStamps as hi, ancestorsOf as hn, readMarker as hr, MAX_WORKSPACE_PORT as ht, deleteReview as i, analysisRefOf as ia, matchingWorkspaceIds as ii, checkArchitecture as in, CODE_COPY_CLASS as ir, ensureServer as it, RUNNER_KINDS as j, isCommitReview as ja, deleteCollection as ji, pruneNotifications as jn, endedAt as jr, liveUpdateFor as jt, queueForReview as k, DetachedHeadError as ka, createCollection as ki, markReadForReview as kn, allJobs as kr, askCheckout as kt, kissAgentId as l, findingIn as la, recentWorkspaces as li, storeArchitecture as ln, isBusy as lr, spawnServer as lt, RUN_KINDS as m, promptGrade as ma, workspaceRevision as mi, REPOSITORY_SCOPE as mn, isWorktreeHeld as mr, DEFAULT_WORKSPACE_PORT as mt, MCP_TOOL_NAMES as n, ANALYSIS_ONLY as na, lineagePosition as ni, formatDuration as nn, AgentCancelledError as no, renderMarkdown as nr, bootstrapUrl as nt, liveJobsFor as o, closesFinding as oa, positionInLineage as oi, partFiles as on, renderInlineText as or, readServerRecord as ot, track as p, isOffered as pa, touchWorkspace as pi, QUOTE_LIMITS as pn, holdWorktree as pr, writeServerRecord as pt, endAskRequest as q, agentById as qa, resolvedByConversation as qi, refreshPrContext as qn, decideKissRecommendation as qr, telemetryUploadEnabled as qt, deleteLineage as r, NO_STATUS as ra, loadWorkspace as ri, ARCHITECTURE_DIR as rn, AgentUnavailableError as ro, CODE_BLOCK_CLASS as rr, clearServerRecordOwnedBy as rt, wasBlocked as s, currentGradeIn as sa, presentedKissRunOf as si, readArchitecture as sn, modelHelpLines as sr, reviewsUrl as st, MCP_SERVER_INFO_NAME as t, withExplanation as ta, lineageKey as ti, describeRuntimes as tn, AGENT_RUN_MARKER as to, GITHUB_MARKDOWN as tr, readIndexToken as tt, recordKissRun as u, findingStatus as ua, reviewedCommit as ui, storedScopes as un, withReviewLock as ur, stopChild as ut, heldRuns as v, wasReassessed as va, activityLabel as vi, announceJob as vn, describeMovement as vr, resolveWorkspacePort as vt, unsupportedReason as w, describeAuthorship as wa, lifecyclePillLabel as wi, createPrUpdate as wn, reviewedShaOf as wr, cancelUpdate as wt, batchIdentity as x, asString$1 as xa, lifecycleItemLabel as xi, categoryOf as xn, checkCodeFreshness as xr, COMMIT_REVIEW_CANNOT_UPDATE as xt, reportRun as y, followUpFindingId as ya, isLifecycle as yi, branchOf as yn, describeSubject as yr, statedWorkspacePort as yt, agentDisplayName as z, resolveModel as za, queueRemove as zi, withUsageRecorded as zn, isTerminalJobPhase as zr, startJob as zt };
|