prreviewbuddy 0.91.1 → 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 +32 -0
- package/dist/main.js +8 -3
- package/dist/{mcp_tools-BR7_XprF.js → mcp_tools-BKPpd9dN.js} +148 -36
- package/dist/server.js +85 -32
- package/package.json +1 -1
- package/static/shell.css +31 -10
- package/static/sidebar.css +25 -6
- package/static/workspace.js +58 -45
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $a as runnableAgents, $i as explanationOf, $n as authorPreview, $r as kissDecisionsOf, $t as recordRuntimeBestEffort, A as settleQueue, Ai as createWithMembers, An as moveIds, Ar as attemptIdOf, At as UpdateAlreadyRunningError, B as humanizeModelId, Ba as agentIdOf, Bi as queueStamp, Bn as existingPaths, Br as phasesFor, C as parsePullRequestLink, Ca as objectWithAnyOf, Ci as lifecyclePillAction, Cn as createPrState, Cr as followedBranch, Ct as RefreshUnavailableError, D as activateQueued, Da as resolveTarget, Di as sectionOf$1, Dn as markAllRead, Dr as fillFileUrlTemplate, E as relativeTime$1, Ea as kissOutcome, Ei as parseLifecycle, En as listNotifications, Er as forgeResolver, Et as mergeUpdateInto, Fa as shorthandOf, Fi as setMembership, Fn as retireNotification, Fr as pruneJobResidue, Ft as prepareReview, G as reviewTag, Ga as STORE_ROOT, Gi as issuesOutstanding, Gn as storedConversation, Gr as isClaimed, Gt as recordTelemetryUploadConsent, H as findingRef, Ha as readAgentPreference, Hi as doneVerb, Hn as adoptLegacyBaseline, Hr as purposeOf, Ht as record, Ia as git, Ii as updateCollections, In as toneOf, Ir as saveJob, It as settleReview, Ja as agentFor$1, Ji as reviewerDispositions, Jn as isUnchanged, Jr as followedRefName, Jt as BUILD_VERSION, K as reviewTagsIn, Ka as AGENT_IDS, Ki as questionsOutstanding, Kn as unforeseenFailure, Kt as telemetryUploadConsent, L as modelProvenanceOf, La as refExists, Li as queueAdd, Ln as unreadAround, Lt as reanalyseReview, Ma as resolveBase, Mi as nameProblemText, Mn as readNotification, Mr as fail$1, Mt as runningJobs, N as cliEntry, Na as AmbiguousRefError, Ni as readCollections, Nn as readStateOf, Nr as isTerminal, Nt as failureOf$1, O as compactQueue, Oa as originRemote, Oi as collectionsStamp, On as markRead, Or as RUN_RECORD_RETENTION_MS, Ot as updateReview, Pa as shortNameOf, Pi as renameCollection, Pn as removeNotification, Pr as loadJob, Pt as observeReview, Q as markAskRunning, Qa as parkedReason, Qi as explanationActionOf, Qn as UNESTABLISHED_MOTIVATION, Qr as kissDecisionRefusal, Qt as mapRuntimes, R as provenanceDetailLines, Ra as resolveAgent, Ri as queueAddMany, Rn as unreadCount$1, Rr as isLiveJob, Rt as runJob, S as extractPullRequestLinks, Sa as extractJsonText, Si as lifecycleName$1, Sn as createArchitectureNotification, Sr as checkReview, St as FETCH_TIMEOUT_MS, T as runBatch, Ta as WITHHELD_REASON, Ti as offersLifecycle, Tn as eventName, Tr as fetchHead, Tt as cancellableHere, U as findingRefs, Ua as writeAgentPreference, Ui as isIssueOutstanding, Un as prepareConversationWithin, V as findingAtRef, Va as clearAgentPreference, Vi as readQueue, Vn as ASK_REREAD_CEILING_MS, Vr as progressSteps, Vt as readEvents, W as refOf, Wi as isQuestionOutstanding, Wn as saveRefresh, X as isRequestId, Xa as detectAgents, Xi as processDiscussion, Xn as EXPLAIN_SIMPLY_PROMPT, Xr as indexKeptIds, Xt as feedbackUrl, Ya as agentIdentityOf, Yi as verdictClosure, Yn as agentEnvOf, Yr as groupByLineage, Za as isAgentId, Zi as recommendationsOf, Zn as chatConversationSection, Zr as indexReviewGroups, Zt as waitingHistory, _ as endRun, _a as statusLookup, _i as activityAttributes, _n as writeJsonAtomically, _r as requestJobStop, _t as parseWorkspacePort, a as lineageIds, aa as assessmentLookup, ai as mutateWorkspace, an as loadArchitecture, ar as escapeHtml$1, b as stopRun, ba as SEVERITIES, bi as lifecycleChip, bn as subjectOf, br as findExistingReview, bt as writePortPreference, c as discardJob, ca as findingAssessment, ci as previousKissResult, cn as repositoryKey, cr as ReviewBeingDeletedError, ct as serverEntryExists, d as startKissJob, da as gradeScale, dn as trackedFiles, dr as MANAGED_ROOT, ea as isExplanationAction, ei as latestKissRun, en as RUNTIME_WORDS, eo as versionFrom, er as hasAuthorContent, f as isDriving, fa as isGradeFor, fi as summarise, fn as ownersOf, fr as createWorktree, g as completeRun, ga as sourcePhrase, gi as LIFECYCLES, gn as isArchitectureId, gr as removeWorktree, gt as MIN_WORKSPACE_PORT, h as beginRun, ha as reassessIn, hi as workspaceStamps, hn as ancestorsOf, hr as readMarker, ht as MAX_WORKSPACE_PORT, i as deleteReview, ia as analysisRefOf, in as checkArchitecture, ir as CODE_COPY_CLASS, ja as isCommitReview, ji as deleteCollection, jn as pruneNotifications, jr as endedAt, jt as liveUpdateFor, ka as DetachedHeadError, ki as createCollection, kn as markReadForReview, kr as allJobs, kt as askCheckout, l as kissAgentId, la as findingIn, li as recentWorkspaces, ln as storeArchitecture, lr as isBusy, lt as spawnServer, m as RUN_KINDS, ma as promptGrade, mi as workspaceRevision, mn as REPOSITORY_SCOPE, mr as isWorktreeHeld, mt as DEFAULT_WORKSPACE_PORT, n as MCP_TOOL_NAMES, na as ANALYSIS_ONLY, ni as lineagePosition, nn as formatDuration, no as AgentCancelledError, nr as renderMarkdown, o as liveJobsFor, oa as closesFinding, on as partFiles, or as renderInlineText, ot as readServerRecord, p as track, pa as isOffered, pi as touchWorkspace, pn as QUOTE_LIMITS, pr as holdWorktree, pt as writeServerRecord, q as endAskRequest, qa as agentById, qi as resolvedByConversation, qn as refreshPrContext, qr as decideKissRecommendation, r as deleteLineage, ra as NO_STATUS, ri as loadWorkspace, rn as ARCHITECTURE_DIR, ro as AgentUnavailableError, rr as CODE_BLOCK_CLASS, rt as clearServerRecordOwnedBy, s as wasBlocked, sa as currentGradeIn, si as presentedKissRunOf, sn as readArchitecture, ta as withExplanation, ti as lineageKey, tn as describeRuntimes, tr as GITHUB_MARKDOWN, tt as readIndexToken, ua as findingStatus, ui as reviewedCommit, un as storedScopes, ur as withReviewLock, ut as stopChild, v as heldRuns, va as wasReassessed, vi as activityLabel, vn as announceJob, vt as resolveWorkspacePort, w as unsupportedReason, wa as describeAuthorship, wi as lifecyclePillLabel, wn as createPrUpdate, wr as reviewedShaOf, wt as cancelUpdate, x as batchIdentity, xa as asString, xi as lifecycleItemLabel, xn as categoryOf, xr as checkCodeFreshness, y as reportRun, ya as followUpFindingId, yi as isLifecycle, yn as branchOf, yt as statedWorkspacePort, z as agentDisplayName, za as resolveModel, zi as queueRemove, zn as withUsageRecorded, zr as isTerminalJobPhase } from "./mcp_tools-
|
|
1
|
+
import { $a as runnableAgents, $i as explanationOf, $n as authorPreview, $r as kissDecisionsOf, $t as recordRuntimeBestEffort, A as settleQueue, Ai as createWithMembers, An as moveIds, Ar as attemptIdOf, At as UpdateAlreadyRunningError, B as humanizeModelId, Ba as agentIdOf, Bi as queueStamp, Bn as existingPaths, Br as phasesFor, C as parsePullRequestLink, Ca as objectWithAnyOf, Ci as lifecyclePillAction, Cn as createPrState, Cr as followedBranch, Ct as RefreshUnavailableError, D as activateQueued, Da as resolveTarget, Di as sectionOf$1, Dn as markAllRead, Dr as fillFileUrlTemplate, E as relativeTime$1, Ea as kissOutcome, Ei as parseLifecycle, En as listNotifications, Er as forgeResolver, Et as mergeUpdateInto, Fa as shorthandOf, Fi as setMembership, Fn as retireNotification, Fr as pruneJobResidue, Ft as prepareReview, G as reviewTag, Ga as STORE_ROOT, Gi as issuesOutstanding, Gn as storedConversation, Gr as isClaimed, Gt as recordTelemetryUploadConsent, H as findingRef, Ha as readAgentPreference, Hi as doneVerb, Hn as adoptLegacyBaseline, Hr as purposeOf, Ht as record, Ia as git, Ii as updateCollections, In as toneOf, Ir as saveJob, It as settleReview, Ja as agentFor$1, Ji as reviewerDispositions, Jn as isUnchanged, Jr as followedRefName, Jt as BUILD_VERSION, K as reviewTagsIn, Ka as AGENT_IDS, Ki as questionsOutstanding, Kn as unforeseenFailure, Kt as telemetryUploadConsent, L as modelProvenanceOf, La as refExists, Li as queueAdd, Ln as unreadAround, Lt as reanalyseReview, Ma as resolveBase, Mi as nameProblemText, Mn as readNotification, Mr as fail$1, Mt as runningJobs, N as cliEntry, Na as AmbiguousRefError, Ni as readCollections, Nn as readStateOf, Nr as isTerminal, Nt as failureOf$1, O as compactQueue, Oa as originRemote, Oi as collectionsStamp, On as markRead, Or as RUN_RECORD_RETENTION_MS, Ot as updateReview, Pa as shortNameOf, Pi as renameCollection, Pn as removeNotification, Pr as loadJob, Pt as observeReview, Q as markAskRunning, Qa as parkedReason, Qi as explanationActionOf, Qn as UNESTABLISHED_MOTIVATION, Qr as kissDecisionRefusal, Qt as mapRuntimes, R as provenanceDetailLines, Ra as resolveAgent, Ri as queueAddMany, Rn as unreadCount$1, Rr as isLiveJob, Rt as runJob, S as extractPullRequestLinks, Sa as extractJsonText, Si as lifecycleName$1, Sn as createArchitectureNotification, Sr as checkReview, St as FETCH_TIMEOUT_MS, T as runBatch, Ta as WITHHELD_REASON, Ti as offersLifecycle, Tn as eventName, Tr as fetchHead, Tt as cancellableHere, U as findingRefs, Ua as writeAgentPreference, Ui as isIssueOutstanding, Un as prepareConversationWithin, V as findingAtRef, Va as clearAgentPreference, Vi as readQueue, Vn as ASK_REREAD_CEILING_MS, Vr as progressSteps, Vt as readEvents, W as refOf, Wi as isQuestionOutstanding, Wn as saveRefresh, X as isRequestId, Xa as detectAgents, Xi as processDiscussion, Xn as EXPLAIN_SIMPLY_PROMPT, Xr as indexKeptIds, Xt as feedbackUrl, Ya as agentIdentityOf, Yi as verdictClosure, Yn as agentEnvOf, Yr as groupByLineage, Za as isAgentId, Zi as recommendationsOf, Zn as chatConversationSection, Zr as indexReviewGroups, Zt as waitingHistory, _ as endRun, _a as statusLookup, _i as activityAttributes, _n as writeJsonAtomically, _r as requestJobStop, _t as parseWorkspacePort, a as lineageIds, aa as assessmentLookup, ai as mutateWorkspace, an as loadArchitecture, ar as escapeHtml$1, b as stopRun, ba as SEVERITIES, bi as lifecycleChip, bn as subjectOf, br as findExistingReview, bt as writePortPreference, c as discardJob, ca as findingAssessment, ci as previousKissResult, cn as repositoryKey, cr as ReviewBeingDeletedError, ct as serverEntryExists, d as startKissJob, da as gradeScale, dn as trackedFiles, dr as MANAGED_ROOT, ea as isExplanationAction, ei as latestKissRun, en as RUNTIME_WORDS, eo as versionFrom, er as hasAuthorContent, f as isDriving, fa as isGradeFor, fi as summarise, fn as ownersOf, fr as createWorktree, g as completeRun, ga as sourcePhrase, gi as LIFECYCLES, gn as isArchitectureId, gr as removeWorktree, gt as MIN_WORKSPACE_PORT, h as beginRun, ha as reassessIn, hi as workspaceStamps, hn as ancestorsOf, hr as readMarker, ht as MAX_WORKSPACE_PORT, i as deleteReview, ia as analysisRefOf, in as checkArchitecture, ir as CODE_COPY_CLASS, ja as isCommitReview, ji as deleteCollection, jn as pruneNotifications, jr as endedAt, jt as liveUpdateFor, ka as DetachedHeadError, ki as createCollection, kn as markReadForReview, kr as allJobs, kt as askCheckout, l as kissAgentId, la as findingIn, li as recentWorkspaces, ln as storeArchitecture, lr as isBusy, lt as spawnServer, m as RUN_KINDS, ma as promptGrade, mi as workspaceRevision, mn as REPOSITORY_SCOPE, mr as isWorktreeHeld, mt as DEFAULT_WORKSPACE_PORT, n as MCP_TOOL_NAMES, na as ANALYSIS_ONLY, ni as lineagePosition, nn as formatDuration, no as AgentCancelledError, nr as renderMarkdown, o as liveJobsFor, oa as closesFinding, on as partFiles, or as renderInlineText, ot as readServerRecord, p as track, pa as isOffered, pi as touchWorkspace, pn as QUOTE_LIMITS, pr as holdWorktree, pt as writeServerRecord, q as endAskRequest, qa as agentById, qi as resolvedByConversation, qn as refreshPrContext, qr as decideKissRecommendation, r as deleteLineage, ra as NO_STATUS, ri as loadWorkspace, rn as ARCHITECTURE_DIR, ro as AgentUnavailableError, rr as CODE_BLOCK_CLASS, rt as clearServerRecordOwnedBy, s as wasBlocked, sa as currentGradeIn, si as presentedKissRunOf, sn as readArchitecture, ta as withExplanation, ti as lineageKey, tn as describeRuntimes, tr as GITHUB_MARKDOWN, tt as readIndexToken, ua as findingStatus, ui as reviewedCommit, un as storedScopes, ur as withReviewLock, ut as stopChild, v as heldRuns, va as wasReassessed, vi as activityLabel, vn as announceJob, vt as resolveWorkspacePort, w as unsupportedReason, wa as describeAuthorship, wi as lifecyclePillLabel, wn as createPrUpdate, wr as reviewedShaOf, wt as cancelUpdate, x as batchIdentity, xa as asString, xi as lifecycleItemLabel, xn as categoryOf, xr as checkCodeFreshness, y as reportRun, ya as followUpFindingId, yi as isLifecycle, yn as branchOf, yt as statedWorkspacePort, z as agentDisplayName, za as resolveModel, zi as queueRemove, zn as withUsageRecorded, zr as isTerminalJobPhase } from "./mcp_tools-BKPpd9dN.js";
|
|
2
2
|
import { basename, delimiter, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { execFile, spawn } from "node:child_process";
|
|
4
4
|
import { accessSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -1573,6 +1573,7 @@ function tallyEntries(entries) {
|
|
|
1573
1573
|
bySection: {},
|
|
1574
1574
|
verify: 0,
|
|
1575
1575
|
decide: 0,
|
|
1576
|
+
fix: 0,
|
|
1576
1577
|
step: 0
|
|
1577
1578
|
};
|
|
1578
1579
|
for (const entry of entries) {
|
|
@@ -1602,6 +1603,7 @@ function issuesAttentionLine(tally) {
|
|
|
1602
1603
|
const steps = [
|
|
1603
1604
|
tally.verify ? count(tally.verify, "verification step", "verification steps") : "",
|
|
1604
1605
|
tally.decide ? count(tally.decide, "decision", "decisions") : "",
|
|
1606
|
+
tally.fix ? count(tally.fix, "fix", "fixes") : "",
|
|
1605
1607
|
tally.step ? count(tally.step, "next step", "next steps") : ""
|
|
1606
1608
|
].filter(Boolean);
|
|
1607
1609
|
return [count(total, "outstanding issue", "outstanding issues"), ...steps].join(" · ");
|
|
@@ -3443,8 +3445,13 @@ function renderIssuesTab(session, investigatingId, options) {
|
|
|
3443
3445
|
${renderFileLocation(issue.file, "pr-helper-issue-loc", issue.line)}
|
|
3444
3446
|
${renderRelatedFiles(issue.relatedFiles)}
|
|
3445
3447
|
${renderInvestigationProvenance("issue", issue.id, records, now)}`;
|
|
3448
|
+
const actions = `<div class="pr-helper-issue-actions">
|
|
3449
|
+
${renderInvestigationActions("issue", issue.id, records, investigatingId)}
|
|
3450
|
+
${renderDismissToggle(issue, isDismissed, stale, dismissals.get(issue.id), dispositions.isClosedByVerdict(issue))}
|
|
3451
|
+
</div>`;
|
|
3446
3452
|
const body = framed ? `${fixed ? "" : renderConsequence(impact)}${explanation}
|
|
3447
3453
|
${renderReconciliationNote(issue.reconciliationNote)}
|
|
3454
|
+
<div class="pr-helper-card-footer">
|
|
3448
3455
|
<details class="pr-helper-issue-technical">
|
|
3449
3456
|
<summary class="pr-helper-issue-technical-summary">Technical details</summary>
|
|
3450
3457
|
<div class="pr-helper-issue-technical-body">
|
|
@@ -3452,7 +3459,10 @@ function renderIssuesTab(session, investigatingId, options) {
|
|
|
3452
3459
|
<p class="pr-helper-issue-technical-title">${renderInlineText(issue.title)}</p>
|
|
3453
3460
|
${technical}
|
|
3454
3461
|
</div>
|
|
3455
|
-
</details
|
|
3462
|
+
</details>
|
|
3463
|
+
${actions}
|
|
3464
|
+
</div>` : `${technical}
|
|
3465
|
+
${actions}`;
|
|
3456
3466
|
const next = impact?.next ? ` data-issue-next="${impact.next.kind ?? "step"}"` : "";
|
|
3457
3467
|
return `
|
|
3458
3468
|
<div class="pr-helper-issue-card ${cardGradeClass("issue", assessment.current)}${issue.reconciliationStatus ? ` pr-helper-issue-${issue.reconciliationStatus}` : ""}${issue.investigationImpact ? ` pr-helper-issue-investigation-${issue.investigationImpact}` : ""}${isDismissed && !stale ? " pr-helper-issue-card-dismissed" : ""}" data-finding-card="${escapeHtml$1(issue.id)}" data-issue-section="${sectionOf(issue)}"${next}>
|
|
@@ -3476,10 +3486,6 @@ function renderIssuesTab(session, investigatingId, options) {
|
|
|
3476
3486
|
${renderStaleDismissal(stale)}
|
|
3477
3487
|
${renderAssessmentRegion("issue", assessment, grading, statusOf("issue", issue.id))}
|
|
3478
3488
|
${body}
|
|
3479
|
-
<div class="pr-helper-issue-actions">
|
|
3480
|
-
${renderInvestigationActions("issue", issue.id, records, investigatingId)}
|
|
3481
|
-
${renderDismissToggle(issue, isDismissed, stale, dismissals.get(issue.id), dispositions.isClosedByVerdict(issue))}
|
|
3482
|
-
</div>
|
|
3483
3489
|
</div>
|
|
3484
3490
|
`;
|
|
3485
3491
|
};
|
|
@@ -3521,7 +3527,8 @@ function renderConsequence(impact) {
|
|
|
3521
3527
|
}
|
|
3522
3528
|
var STEP_LABELS = {
|
|
3523
3529
|
verify: "To verify:",
|
|
3524
|
-
decide: "To decide:"
|
|
3530
|
+
decide: "To decide:",
|
|
3531
|
+
fix: "To fix:"
|
|
3525
3532
|
};
|
|
3526
3533
|
function renderConsequenceStep(step) {
|
|
3527
3534
|
if (!step) return "";
|
|
@@ -3616,13 +3623,47 @@ function renderQuestionCard(q, sections, answered, records, now = Date.now(), in
|
|
|
3616
3623
|
const answerToggle = `<button type="button" class="pr-helper-question-answer-toggle" data-question-answered="${escapeHtml$1(q.id)}" data-answered="${answered}"${settled ? " data-settled=\"true\"" : ""}${verdictClosed ? " data-verdict-closed=\"true\"" : ""}>${answered ? "Mark as unanswered" : "Mark answered"}</button>`;
|
|
3617
3624
|
const investigationAnswer = q.investigationAnswer?.trim() ? `<h5>Answer from investigation</h5><p class="pr-helper-issue-desc pr-helper-investigation-answer">${renderInlineText(q.investigationAnswer)}</p>` : "";
|
|
3618
3625
|
const reconciliationAnswer = q.reconciliationAnswer?.trim() ? `<h5>${escapeHtml$1(reconciledAnswerHeading(q.reconciledAgainst))}</h5><p class="pr-helper-issue-desc pr-helper-investigation-answer">${renderInlineText(q.reconciliationAnswer)}</p>` : "";
|
|
3626
|
+
const why = q.whyThisMatters ? `<h5>Why this matters</h5><p class="pr-helper-issue-desc">${renderInlineText(q.whyThisMatters)}</p>` : "";
|
|
3627
|
+
const files = q.file || q.relatedFiles?.length ? `<h5>Files</h5>${renderFileLocation(q.file, "pr-helper-issue-loc", void 0)}${renderRelatedFiles(q.relatedFiles)}` : "";
|
|
3628
|
+
const provenance = renderInvestigationProvenance("question", q.id, records, now);
|
|
3629
|
+
const framing = q.framing;
|
|
3630
|
+
const actions = `<div class="pr-helper-question-actions">
|
|
3631
|
+
${jumpLink}
|
|
3632
|
+
<div class="pr-helper-question-actions-group">
|
|
3633
|
+
${renderInvestigationActions("question", q.id, records, investigatingId)}
|
|
3634
|
+
${answerToggle}
|
|
3635
|
+
</div>
|
|
3636
|
+
</div>`;
|
|
3637
|
+
const answers = `${reconciliationAnswer}
|
|
3638
|
+
${renderReconciliationNote(q.reconciliationNote)}
|
|
3639
|
+
${investigationAnswer}`;
|
|
3640
|
+
const body = framing ? `${renderQuestionFraming(framing)}${renderCardExplanation(explanation, options)}
|
|
3641
|
+
${answers}
|
|
3642
|
+
<div class="pr-helper-card-footer">
|
|
3643
|
+
<details class="pr-helper-issue-technical">
|
|
3644
|
+
<summary class="pr-helper-issue-technical-summary">Technical context</summary>
|
|
3645
|
+
<div class="pr-helper-issue-technical-body">
|
|
3646
|
+
<p class="pr-helper-issue-technical-title">${renderInlineText(q.question)}</p>
|
|
3647
|
+
${why}
|
|
3648
|
+
${renderInvestigationNote(q.investigationNote)}
|
|
3649
|
+
${files}
|
|
3650
|
+
${provenance}
|
|
3651
|
+
</div>
|
|
3652
|
+
</details>
|
|
3653
|
+
${actions}
|
|
3654
|
+
</div>` : `${why}${renderCardExplanation(explanation, options)}
|
|
3655
|
+
${answers}
|
|
3656
|
+
${renderInvestigationNote(q.investigationNote)}
|
|
3657
|
+
${files}
|
|
3658
|
+
${provenance}
|
|
3659
|
+
${actions}`;
|
|
3619
3660
|
return `
|
|
3620
3661
|
<div class="pr-helper-question-card${answered ? " pr-helper-question-card-answered" : ""}${q.investigationImpact ? ` pr-helper-issue-investigation-${q.investigationImpact}` : ""}" data-finding-card="${escapeHtml$1(q.id)}"${questionHome(q) ? ` data-section-id="${escapeHtml$1(questionHome(q))}"` : ""}>
|
|
3621
3662
|
<div class="pr-helper-issue-header">
|
|
3622
3663
|
<div class="pr-helper-issue-title-row">
|
|
3623
3664
|
${options?.feedbackSelect ? renderFeedbackPick("question", q.question, questionFeedbackMarkdown(q), ref) : ""}
|
|
3624
3665
|
${renderFindingRef(ref)}
|
|
3625
|
-
<p class="pr-helper-issue-title">${renderInlineText(q.question)}</p>
|
|
3666
|
+
<p class="pr-helper-issue-title">${renderInlineText(framing?.question ?? q.question)}</p>
|
|
3626
3667
|
${renderFindingCopySource(questionMarkdown(q, assessment), "question")}
|
|
3627
3668
|
${options?.askBuddy ? renderAskBuddyMenu("question") : ""}
|
|
3628
3669
|
</div>
|
|
@@ -3639,23 +3680,17 @@ function renderQuestionCard(q, sections, answered, records, now = Date.now(), in
|
|
|
3639
3680
|
</div>
|
|
3640
3681
|
</div>
|
|
3641
3682
|
${renderAssessmentRegion("question", assessment, grading, status)}
|
|
3642
|
-
${
|
|
3643
|
-
${reconciliationAnswer}
|
|
3644
|
-
${renderReconciliationNote(q.reconciliationNote)}
|
|
3645
|
-
${investigationAnswer}
|
|
3646
|
-
${renderInvestigationNote(q.investigationNote)}
|
|
3647
|
-
${q.file || q.relatedFiles?.length ? `<h5>Files</h5>${renderFileLocation(q.file, "pr-helper-issue-loc", void 0)}${renderRelatedFiles(q.relatedFiles)}` : ""}
|
|
3648
|
-
${renderInvestigationProvenance("question", q.id, records, now)}
|
|
3649
|
-
<div class="pr-helper-question-actions">
|
|
3650
|
-
${jumpLink}
|
|
3651
|
-
<div class="pr-helper-question-actions-group">
|
|
3652
|
-
${renderInvestigationActions("question", q.id, records, investigatingId)}
|
|
3653
|
-
${answerToggle}
|
|
3654
|
-
</div>
|
|
3655
|
-
</div>
|
|
3683
|
+
${body}
|
|
3656
3684
|
</div>
|
|
3657
3685
|
`;
|
|
3658
3686
|
}
|
|
3687
|
+
/** What the question means, read first: why the answer matters and what is needed. */
|
|
3688
|
+
function renderQuestionFraming(framing) {
|
|
3689
|
+
return `<div class="pr-helper-issue-impact">
|
|
3690
|
+
<p class="pr-helper-issue-scenario">${renderInlineText(framing.why)}</p>
|
|
3691
|
+
${framing.needed ? `<p class="pr-helper-issue-next pr-helper-question-needed"><span class="pr-helper-issue-next-label">Needed:</span> ${renderInlineText(framing.needed)}</p>` : ""}
|
|
3692
|
+
</div>`;
|
|
3693
|
+
}
|
|
3659
3694
|
/**
|
|
3660
3695
|
* The counter's contents, split out so a caller that toggles one question can refresh it without
|
|
3661
3696
|
* re-rendering the tab.
|
|
@@ -6957,20 +6992,28 @@ function renderStandardViews(view, sections) {
|
|
|
6957
6992
|
* When the "already raised" claims below were last true.
|
|
6958
6993
|
*
|
|
6959
6994
|
* Every attribution on this view carries a thread's state — "still unresolved", "since marked
|
|
6960
|
-
* resolved" — and that state was frozen the moment the conversation was imported. Nothing
|
|
6961
|
-
* re-checks it
|
|
6962
|
-
*
|
|
6995
|
+
* resolved" — and that state was frozen the moment the conversation was imported. Nothing on this
|
|
6996
|
+
* view re-checks it; the PR context view does, on request. Until then a card can go on telling the
|
|
6997
|
+
* reviewer that Sergei's thread is open an hour after Sergei closed it.
|
|
6963
6998
|
*
|
|
6964
6999
|
* Every other kind of staleness in this product degrades into vagueness. This one degrades into a
|
|
6965
7000
|
* confident, specific, wrong claim about what a named colleague currently thinks, which is worth
|
|
6966
|
-
* one line above the list
|
|
7001
|
+
* one line above the list: its age always in view, the explanation one disclosure away, and the way
|
|
7002
|
+
* to the re-check beside it.
|
|
6967
7003
|
*
|
|
6968
7004
|
* Only where a conversation was attached: there are no such claims to qualify otherwise.
|
|
6969
7005
|
*/
|
|
6970
7006
|
function renderAttributionAge(view) {
|
|
6971
7007
|
if (!view.prContext) return "";
|
|
6972
7008
|
const imported = relativeTime$1(view.prContext.prContext.discussion.fetchedAt);
|
|
6973
|
-
return `<
|
|
7009
|
+
return `<div class="prb-discussion-age">
|
|
7010
|
+
<details class="prb-discussion-age-detail">
|
|
7011
|
+
<summary class="prb-discussion-age-summary">PR discussion checked ${escapeHtml$1(imported)}</summary>
|
|
7012
|
+
<p class="prb-discussion-age-body">Any “already raised” note below, and whether each thread was still open, describes the pull request as it stood when its discussion was fetched. A reply or a resolved thread since then is not reflected here until the conversation is re-checked.</p>
|
|
7013
|
+
</details>
|
|
7014
|
+
<span class="prb-discussion-age-sep" aria-hidden="true">·</span>
|
|
7015
|
+
<button type="button" class="prb-doc-note-link" data-view-nav="prcontext">Re-check in PR context</button>
|
|
7016
|
+
</div>`;
|
|
6974
7017
|
}
|
|
6975
7018
|
/**
|
|
6976
7019
|
* The link out to this file on the pull request.
|
|
@@ -12690,11 +12733,21 @@ feature: E</pre>
|
|
|
12690
12733
|
confirm</b> where the behaviour is right only if it was meant, and <b>Maintenance</b> for what it
|
|
12691
12734
|
costs later. Within each group the most severe come first. Severity and confidence are shown on
|
|
12692
12735
|
each card, separately from its group.</p>
|
|
12693
|
-
<p>A card leads with what the issue means and when it happens, then the step
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12736
|
+
<p>A card leads with what the issue means and when it happens, then the step it calls for, when
|
|
12737
|
+
there is one: <b>To verify</b> settles whether it happens, <b>To decide</b> asks whether it was
|
|
12738
|
+
meant, and <b>To fix</b> names the change that would correct it. The technical account, where it
|
|
12739
|
+
is in the code and its history are under <b>Technical details</b> on the card. Folding a group is
|
|
12740
|
+
remembered for the next review.</p>
|
|
12741
|
+
<p>Issues from older reviews have no summary yet and are under <b>Other issues</b>. The next
|
|
12742
|
+
Update that finds new commits or new discussion writes one for each issue still outstanding,
|
|
12743
|
+
from the same evidence; it does not re-check the issue. An Update that finds nothing new changes
|
|
12744
|
+
nothing.</p>
|
|
12745
|
+
<p>Questions read the same way: each leads with the question in plain terms, why the answer
|
|
12746
|
+
matters and what is needed, with the original question and its files under <b>Technical
|
|
12747
|
+
context</b>. Any answer so far stays on the card.</p>
|
|
12748
|
+
<p>When the review came with a pull request discussion, the line above the issues says when it
|
|
12749
|
+
was last checked. Its “already raised” notes describe the discussion as it was then; <b>Re-check
|
|
12750
|
+
in PR context</b> takes you to bring it up to date.</p>
|
|
12698
12751
|
<p>Resolved and dismissed issues are in the closed list at the bottom. One the new commits fixed
|
|
12699
12752
|
leads with what the code now does, when the update could see it.</p>`
|
|
12700
12753
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prreviewbuddy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.92.0",
|
|
4
4
|
"description": "Understand code changes before you approve them. Local branch and pull request reviews with Claude Code or Codex.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://prreviewbuddy.com",
|
package/static/shell.css
CHANGED
|
@@ -2386,10 +2386,6 @@ a.prb-rail-item { text-decoration: none; }
|
|
|
2386
2386
|
line-height: var(--lh-body);
|
|
2387
2387
|
}
|
|
2388
2388
|
|
|
2389
|
-
/* A caveat above a list, in the light pane. Pane literals, not shell tokens — see
|
|
2390
|
-
pane_palette.test.ts for why this is a rule and not a preference. */
|
|
2391
|
-
/* Full width, because it introduces the cards below it and a narrower block reads as a floating
|
|
2392
|
-
aside rather than as the heading note it is. */
|
|
2393
2389
|
/* The control named in the note, as the control rather than as bold text. It goes to the view that
|
|
2394
2390
|
holds it, because a sentence that tells the reviewer where something is and cannot take them
|
|
2395
2391
|
there is asking them to do the navigating twice. */
|
|
@@ -2405,16 +2401,41 @@ a.prb-rail-item { text-decoration: none; }
|
|
|
2405
2401
|
}
|
|
2406
2402
|
.prb-doc-note-link:hover { color: var(--pane-ink); }
|
|
2407
2403
|
|
|
2408
|
-
.
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2404
|
+
/* The age of the "already raised" claims, as one quiet line above the Issues orientation. */
|
|
2405
|
+
.prb-discussion-age {
|
|
2406
|
+
display: flex;
|
|
2407
|
+
flex-wrap: wrap;
|
|
2408
|
+
align-items: baseline;
|
|
2409
|
+
column-gap: 6px;
|
|
2410
|
+
margin: 0 0 12px;
|
|
2414
2411
|
color: var(--pane-ink-muted);
|
|
2415
2412
|
font-size: var(--t-meta);
|
|
2416
2413
|
line-height: var(--lh-body);
|
|
2417
2414
|
}
|
|
2415
|
+
.prb-discussion-age-summary {
|
|
2416
|
+
cursor: pointer;
|
|
2417
|
+
list-style: none;
|
|
2418
|
+
}
|
|
2419
|
+
.prb-discussion-age-summary::-webkit-details-marker { display: none; }
|
|
2420
|
+
.prb-discussion-age-summary::before {
|
|
2421
|
+
content: '';
|
|
2422
|
+
display: inline-block;
|
|
2423
|
+
margin-right: 6px;
|
|
2424
|
+
vertical-align: 1px;
|
|
2425
|
+
border-left: 5px solid currentColor;
|
|
2426
|
+
border-top: 4px solid transparent;
|
|
2427
|
+
border-bottom: 4px solid transparent;
|
|
2428
|
+
}
|
|
2429
|
+
.prb-discussion-age-detail[open] > .prb-discussion-age-summary::before { transform: rotate(90deg); }
|
|
2430
|
+
.prb-discussion-age-summary:hover { color: var(--pane-ink); }
|
|
2431
|
+
/* Open, the explanation takes the row, and the re-check follows it on its own line. */
|
|
2432
|
+
.prb-discussion-age-detail[open] { flex-basis: 100%; }
|
|
2433
|
+
.prb-discussion-age-detail[open] ~ .prb-discussion-age-sep { display: none; }
|
|
2434
|
+
.prb-discussion-age-body {
|
|
2435
|
+
margin: 6px 0 4px;
|
|
2436
|
+
padding-left: 11px;
|
|
2437
|
+
border-left: 2px solid var(--pane-line);
|
|
2438
|
+
}
|
|
2418
2439
|
|
|
2419
2440
|
.prb-pr-asof {
|
|
2420
2441
|
flex-basis: 100%;
|
package/static/sidebar.css
CHANGED
|
@@ -1068,7 +1068,7 @@
|
|
|
1068
1068
|
.pr-helper-issue-card {
|
|
1069
1069
|
border: 1px solid var(--color-border-default, #d0d7de);
|
|
1070
1070
|
border-radius: 8px;
|
|
1071
|
-
padding:
|
|
1071
|
+
padding: 12px 14px;
|
|
1072
1072
|
margin-bottom: 12px;
|
|
1073
1073
|
/* Stated rather than inherited: the surface behind this is now the grey canvas. */
|
|
1074
1074
|
background: #ffffff;
|
|
@@ -1437,7 +1437,7 @@
|
|
|
1437
1437
|
.pr-helper-question-card {
|
|
1438
1438
|
border: 1px solid var(--color-border-default, #d0d7de);
|
|
1439
1439
|
border-radius: 8px;
|
|
1440
|
-
padding:
|
|
1440
|
+
padding: 12px 14px;
|
|
1441
1441
|
margin-bottom: 12px;
|
|
1442
1442
|
/* Stated rather than inherited: the surface behind this is now the grey canvas. */
|
|
1443
1443
|
background: #ffffff;
|
|
@@ -1447,6 +1447,9 @@
|
|
|
1447
1447
|
card would throw away the reviewer's own record that they resolved it. The check mark is the
|
|
1448
1448
|
whole "done" signal; nothing else about the card recedes. */
|
|
1449
1449
|
.pr-helper-question-card-answered { box-shadow: inset 3px 0 0 #1a7f37; }
|
|
1450
|
+
/* What an answer still needs is moot once the question is settled, and a tick moves the card here
|
|
1451
|
+
without a redraw, so the drawer is what decides it. */
|
|
1452
|
+
.pr-helper-closed-findings .pr-helper-question-needed { display: none; }
|
|
1450
1453
|
|
|
1451
1454
|
.pr-helper-question-card h5 {
|
|
1452
1455
|
font-size: 10px;
|
|
@@ -1598,14 +1601,15 @@
|
|
|
1598
1601
|
}
|
|
1599
1602
|
|
|
1600
1603
|
.pr-helper-issues-orientation-text {
|
|
1601
|
-
font-size:
|
|
1604
|
+
font-size: 14px;
|
|
1605
|
+
color: var(--color-fg-default, #1f2328);
|
|
1602
1606
|
line-height: 1.5;
|
|
1603
1607
|
margin: 0 0 4px;
|
|
1604
1608
|
overflow-wrap: anywhere;
|
|
1605
1609
|
}
|
|
1606
1610
|
|
|
1607
1611
|
.pr-helper-issues-attention {
|
|
1608
|
-
font-size:
|
|
1612
|
+
font-size: 13px;
|
|
1609
1613
|
font-weight: 600;
|
|
1610
1614
|
color: var(--color-fg-muted, #57606a);
|
|
1611
1615
|
margin: 0;
|
|
@@ -1713,6 +1717,21 @@
|
|
|
1713
1717
|
drawer, smaller and muted, because it belongs to one card rather than to the pane. */
|
|
1714
1718
|
.pr-helper-issue-technical { margin-top: 8px; }
|
|
1715
1719
|
|
|
1720
|
+
/* A framed card's disclosure and actions share a row: closed, the summary sits left and the actions
|
|
1721
|
+
right; opened, the disclosure takes the row and the actions wrap below its body. */
|
|
1722
|
+
.pr-helper-card-footer {
|
|
1723
|
+
display: flex;
|
|
1724
|
+
flex-wrap: wrap;
|
|
1725
|
+
align-items: center;
|
|
1726
|
+
column-gap: 12px;
|
|
1727
|
+
row-gap: 8px;
|
|
1728
|
+
margin-top: 8px;
|
|
1729
|
+
}
|
|
1730
|
+
.pr-helper-card-footer > .pr-helper-issue-technical { flex: 1 1 auto; min-width: 0; margin-top: 0; }
|
|
1731
|
+
.pr-helper-card-footer > .pr-helper-issue-technical[open] { flex-basis: 100%; }
|
|
1732
|
+
.pr-helper-card-footer > .pr-helper-issue-actions,
|
|
1733
|
+
.pr-helper-card-footer > .pr-helper-question-actions { margin-top: 0; margin-left: auto; }
|
|
1734
|
+
|
|
1716
1735
|
.pr-helper-issue-technical-summary {
|
|
1717
1736
|
display: inline-flex;
|
|
1718
1737
|
align-items: center;
|
|
@@ -1769,7 +1788,7 @@
|
|
|
1769
1788
|
justify-content: space-between;
|
|
1770
1789
|
flex-wrap: wrap;
|
|
1771
1790
|
gap: 12px;
|
|
1772
|
-
margin-top:
|
|
1791
|
+
margin-top: 8px;
|
|
1773
1792
|
}
|
|
1774
1793
|
|
|
1775
1794
|
/* Deliberately not a filled button, matching .pr-helper-guide-start-cta: this is "here's the
|
|
@@ -5000,7 +5019,7 @@
|
|
|
5000
5019
|
align-items: center;
|
|
5001
5020
|
justify-content: flex-end;
|
|
5002
5021
|
gap: 12px;
|
|
5003
|
-
margin-top:
|
|
5022
|
+
margin-top: 8px;
|
|
5004
5023
|
}
|
|
5005
5024
|
|
|
5006
5025
|
/* margin-left:auto rather than relying on the row's space-between: the jump link beside it is
|