@vypdev/copilot 3.9.3 → 3.10.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/action.yml +5 -0
- package/build/api/index.js +208 -52
- package/build/api/src/data/model/application_error.d.ts +18 -1
- package/build/api/src/domain/bugbot/context.d.ts +2 -0
- package/build/api/src/domain/bugbot/finding.d.ts +11 -7
- package/build/cli/index.js +1957 -131
- package/build/github_action/index.js +2291 -120
- package/build/web/assets/{index-CsboG2sG.js → index-CNXf8Vmj.js} +1 -1
- package/build/web/index.html +1 -1
- package/package.json +2 -1
- package/setup/actions/copilot-verification-setup/action.yml +13 -0
- package/setup/workflows/copilot_commit.yml +2 -0
- package/setup/workflows/copilot_issue.yml +2 -0
- package/setup/workflows/copilot_issue_comment.yml +20 -106
- package/setup/workflows/copilot_pull_request.yml +2 -0
- package/setup/workflows/copilot_pull_request_comment.yml +20 -106
- package/setup/workflows/copilot_pull_request_review_state.yml +2 -0
- package/setup/workflows/hotfix_workflow.yml +1 -0
- package/setup/workflows/release_workflow.yml +1 -0
package/action.yml
CHANGED
|
@@ -53,6 +53,9 @@ inputs:
|
|
|
53
53
|
pre-branch-sdd:
|
|
54
54
|
description: "Require a validated SDD first commit for started feature and contract-change issues. Requires issue-managed-branches."
|
|
55
55
|
default: "false"
|
|
56
|
+
verification-setup:
|
|
57
|
+
description: "Run the trusted repository composite action before repository verification in generated workflows. Disabled by default."
|
|
58
|
+
default: "false"
|
|
56
59
|
issue-workflow-profile:
|
|
57
60
|
description: "JSON profile of enabled issue workflows."
|
|
58
61
|
default: ""
|
|
@@ -558,6 +561,8 @@ outputs:
|
|
|
558
561
|
runs:
|
|
559
562
|
using: "node24"
|
|
560
563
|
main: "build/github_action/index.js"
|
|
564
|
+
post: "build/github_action/index.js"
|
|
565
|
+
post-if: "always() && env.COPILOT_NATIVE_PHASE != ''"
|
|
561
566
|
branding:
|
|
562
567
|
icon: "cpu"
|
|
563
568
|
color: "blue"
|
package/build/api/index.js
CHANGED
|
@@ -68,6 +68,45 @@ function runAtApplicationErrorBoundary(operation) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
/***/ }),
|
|
72
|
+
|
|
73
|
+
/***/ 2937:
|
|
74
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
78
|
+
exports.BugbotMutationError = void 0;
|
|
79
|
+
exports.bugbotMutationError = bugbotMutationError;
|
|
80
|
+
const application_error_1 = __nccwpck_require__(5999);
|
|
81
|
+
const pull_request_review_errors_1 = __nccwpck_require__(6445);
|
|
82
|
+
class BugbotMutationError extends application_error_1.ApplicationError {
|
|
83
|
+
constructor(diagnostic) {
|
|
84
|
+
super(diagnostic.errorCode, `Bugbot ${diagnostic.stage} failed: operation=${diagnostic.operation}; finding=${diagnostic.findingId}; affected=${diagnostic.affectedCount}; ${diagnostic.providerStatus}; provider-reference=${diagnostic.providerReference}. Completed effects are retained; correct the named cause and recheck the same target.`);
|
|
85
|
+
this.diagnostic = diagnostic;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.BugbotMutationError = BugbotMutationError;
|
|
89
|
+
function bugbotMutationError(cause, stage, findingIds, fallback, affectedCount = findingIds.length) {
|
|
90
|
+
if (cause instanceof BugbotMutationError)
|
|
91
|
+
return cause;
|
|
92
|
+
const provider = cause instanceof pull_request_review_errors_1.PullRequestReviewOperationError ? cause : undefined;
|
|
93
|
+
const status = provider?.providerStatus;
|
|
94
|
+
const errorCode = status === 401 ? 'authorization.credential-invalid' : status === 403 ? 'authorization.denied'
|
|
95
|
+
: status === 404 ? 'provider.not-found' : status === 409 ? 'provider.conflict'
|
|
96
|
+
: status === 429 ? 'provider.rate-limited'
|
|
97
|
+
: status === 408 || status === 425 ? 'provider.unavailable'
|
|
98
|
+
: status && status < 500 ? 'provider.contract-invalid' : 'provider.unavailable';
|
|
99
|
+
const first = findingIds[0];
|
|
100
|
+
return new BugbotMutationError(Object.freeze({
|
|
101
|
+
stage, operation: provider?.operation ?? fallback,
|
|
102
|
+
findingId: typeof first === 'string' && /^[A-Za-z0-9_./:-]{1,200}$/.test(first) ? first : 'unavailable',
|
|
103
|
+
affectedCount: Math.min(affectedCount, 10000),
|
|
104
|
+
providerStatus: status ? `http-${status}` : 'http-unavailable',
|
|
105
|
+
providerReference: provider?.providerReference ?? 'unavailable', errorCode,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
71
110
|
/***/ }),
|
|
72
111
|
|
|
73
112
|
/***/ 601:
|
|
@@ -796,6 +835,7 @@ exports.BUGBOT_MESSAGE_IDS = Object.freeze([
|
|
|
796
835
|
'bugbot.overflow.body',
|
|
797
836
|
'bugbot.common.more',
|
|
798
837
|
'bugbot.diagnostic.operationFailed',
|
|
838
|
+
'bugbot.diagnostic.findingMutationFailed',
|
|
799
839
|
'bugbot.diagnostic.identityUnavailable',
|
|
800
840
|
'bugbot.diagnostic.pullRequestCommentsFailed',
|
|
801
841
|
'bugbot.diagnostic.reviewThreadsFailed',
|
|
@@ -881,6 +921,7 @@ const ENGLISH_MESSAGES = Object.freeze({
|
|
|
881
921
|
'bugbot.overflow.heading': 'More findings (comment limit)',
|
|
882
922
|
'bugbot.overflow.body': Object.freeze({ one: 'There is {count} more finding that was not published as an individual comment. Review locally or in the full diff to see the list.', other: 'There are {count} more findings that were not published as individual comments. Review locally or in the full diff to see the list.' }),
|
|
883
923
|
'bugbot.common.more': Object.freeze({ one: 'and {count} more.', other: 'and {count} more.' }),
|
|
924
|
+
'bugbot.diagnostic.findingMutationFailed': 'Finding mutation failed: stage={stage}; operation={operation}; finding={findingId}; affected={affectedCount}; {providerStatus}; provider reference={providerReference}. Completed effects are retained. Correct access/contract errors before retrying; for transient failures restore provider availability, then recheck the same PR. Recheck reconciles existing reviews and threads.',
|
|
884
925
|
'bugbot.diagnostic.operationFailed': 'Bugbot could not complete one or more finding mutations.',
|
|
885
926
|
'bugbot.diagnostic.identityUnavailable': 'The authenticated Bugbot identity is unavailable.',
|
|
886
927
|
'bugbot.diagnostic.pullRequestCommentsFailed': 'Unable to re-read pull request review comments.',
|
|
@@ -970,6 +1011,7 @@ const SPANISH_MESSAGES = Object.freeze({
|
|
|
970
1011
|
'bugbot.overflow.heading': 'Más hallazgos (límite de comentarios)',
|
|
971
1012
|
'bugbot.overflow.body': Object.freeze({ one: 'Hay {count} hallazgo más que no se publicó como comentario individual. Revísalo localmente o en el diff completo para consultar la lista.', many: 'Hay {count} hallazgos más que no se publicaron como comentarios individuales. Revísalos localmente o en el diff completo para consultar la lista.', other: 'Hay {count} hallazgos más que no se publicaron como comentarios individuales. Revísalos localmente o en el diff completo para consultar la lista.' }),
|
|
972
1013
|
'bugbot.common.more': Object.freeze({ one: 'y {count} más.', many: 'y {count} más.', other: 'y {count} más.' }),
|
|
1014
|
+
'bugbot.diagnostic.findingMutationFailed': 'Falló una mutación: fase={stage}; operación={operation}; hallazgo={findingId}; afectados={affectedCount}; {providerStatus}; referencia del proveedor={providerReference}. Se conservan los efectos completados. Corrige acceso/contrato antes de reintentar; para fallos transitorios restaura el proveedor y revisa la misma PR. La revisión reconcilia comentarios e hilos existentes.',
|
|
973
1015
|
'bugbot.diagnostic.operationFailed': 'Bugbot no pudo completar una o más mutaciones de hallazgos.',
|
|
974
1016
|
'bugbot.diagnostic.identityUnavailable': 'La identidad autenticada de Bugbot no está disponible.',
|
|
975
1017
|
'bugbot.diagnostic.pullRequestCommentsFailed': 'No se pudieron volver a leer los comentarios del review del pull request.',
|
|
@@ -1009,6 +1051,7 @@ async function resolveBugbotCatalog(locale, configuration, resolver) {
|
|
|
1009
1051
|
}
|
|
1010
1052
|
function renderBugbotDiagnostic(diagnostic, catalog) {
|
|
1011
1053
|
switch (diagnostic.code) {
|
|
1054
|
+
case 'finding-mutation-failed': return catalog.message('bugbot.diagnostic.findingMutationFailed', { ...diagnostic.mutation });
|
|
1012
1055
|
case 'operation-failed': return catalog.message('bugbot.diagnostic.operationFailed');
|
|
1013
1056
|
case 'identity-unavailable': return catalog.message('bugbot.diagnostic.identityUnavailable');
|
|
1014
1057
|
case 'snapshot-pull-request-comments-failed': return catalog.message('bugbot.diagnostic.pullRequestCommentsFailed');
|
|
@@ -1558,6 +1601,10 @@ function renderBugbotStatusCard(projection, catalogOrLocale, links) {
|
|
|
1558
1601
|
facts.push(catalog.message('bugbot.coverage.omitted', { count: source.omittedItems }));
|
|
1559
1602
|
if (source.truncatedItems > 0)
|
|
1560
1603
|
facts.push(catalog.message('bugbot.coverage.truncated', { count: source.truncatedItems }));
|
|
1604
|
+
const truncatedIds = source.truncatedItemIds?.slice(0, 50)
|
|
1605
|
+
.filter(id => /^(?:issue:[0-9]+|review:[A-Za-z0-9_=-]+)$/.test(id) && id.length <= 160);
|
|
1606
|
+
if (truncatedIds?.length)
|
|
1607
|
+
facts.push(`truncated-source-ids=${truncatedIds.join(', ')}`);
|
|
1561
1608
|
if (source.providerLimitReached)
|
|
1562
1609
|
facts.push(catalog.message('bugbot.coverage.providerLimit'));
|
|
1563
1610
|
return `- ${source.source}: ${source.status}; ${facts.join(', ')}`;
|
|
@@ -1647,9 +1694,21 @@ function normalizeHistoricalSnapshot(originalBody, analyzedHeadSha, catalog) {
|
|
|
1647
1694
|
function renderFindingRow(finding) {
|
|
1648
1695
|
const label = (0, github_comment_publication_policy_1.sanitizeAgentMarkdown)(finding.title || finding.id, 500).replace(/[\r\n]+/gu, ' ');
|
|
1649
1696
|
const state = stateLabel(finding.state);
|
|
1697
|
+
const identity = finding.state === 'unknown'
|
|
1698
|
+
? ` — ${renderFindingId(finding.id)}`
|
|
1699
|
+
: '';
|
|
1650
1700
|
return finding.url
|
|
1651
|
-
? `- ${state} — [${label}](${finding.url})`
|
|
1652
|
-
: `- ${state} — ${label}`;
|
|
1701
|
+
? `- ${state} — [${label}](${finding.url})${identity}`
|
|
1702
|
+
: `- ${state} — ${label}${identity}`;
|
|
1703
|
+
}
|
|
1704
|
+
function renderFindingId(value) {
|
|
1705
|
+
const id = (0, github_comment_publication_policy_1.sanitizeAgentMarkdown)(value, 200).replace(/[\r\n]+/gu, ' ');
|
|
1706
|
+
// A delimiter longer than every embedded backtick run keeps links, images
|
|
1707
|
+
// and HTML inert even when the marker permits arbitrary Markdown punctuation.
|
|
1708
|
+
let delimiter = '`';
|
|
1709
|
+
while (id.includes(delimiter))
|
|
1710
|
+
delimiter += '`';
|
|
1711
|
+
return `${delimiter} ${id} ${delimiter}`;
|
|
1653
1712
|
}
|
|
1654
1713
|
function stateLabel(state) {
|
|
1655
1714
|
return `[ ] ${state}`;
|
|
@@ -2136,6 +2195,13 @@ class PullRequestReviewOperationError extends Error {
|
|
|
2136
2195
|
super(buildMessage(operation, context));
|
|
2137
2196
|
this.name = "PullRequestReviewOperationError";
|
|
2138
2197
|
this.operation = operation;
|
|
2198
|
+
const status = context?.providerStatus;
|
|
2199
|
+
if (typeof status === 'number' && Number.isInteger(status) && status >= 400 && status <= 599) {
|
|
2200
|
+
this.providerStatus = status;
|
|
2201
|
+
}
|
|
2202
|
+
if (typeof context?.providerReference === 'string' && /^[A-Za-z0-9:-]{1,64}$/.test(context.providerReference)) {
|
|
2203
|
+
this.providerReference = context.providerReference;
|
|
2204
|
+
}
|
|
2139
2205
|
}
|
|
2140
2206
|
}
|
|
2141
2207
|
exports.PullRequestReviewOperationError = PullRequestReviewOperationError;
|
|
@@ -2235,7 +2301,7 @@ function partitionFailureCategory(error) {
|
|
|
2235
2301
|
return error instanceof Error ? error.name : 'unknown';
|
|
2236
2302
|
}
|
|
2237
2303
|
function suppressDismissedFindings(execution, context, prepared) {
|
|
2238
|
-
const activeFindings = (prepared.activeFindings ?? prepared.toPublish).filter((finding) => {
|
|
2304
|
+
const activeFindings = (0, finding_1.retainExistingFindingIds)(prepared.activeFindings ?? prepared.toPublish, context.existingByFindingId).filter((finding) => {
|
|
2239
2305
|
const existing = (0, finding_1.findExistingFindingInfo)(context.existingByFindingId, finding);
|
|
2240
2306
|
return existing?.issue?.resolution !== 'dismissed' && existing?.pullRequest?.resolution !== 'dismissed';
|
|
2241
2307
|
});
|
|
@@ -2254,6 +2320,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
2254
2320
|
exports.applyDetectedFindings = applyDetectedFindings;
|
|
2255
2321
|
const mark_findings_resolved_use_case_1 = __nccwpck_require__(6963);
|
|
2256
2322
|
const publish_findings_use_case_1 = __nccwpck_require__(8442);
|
|
2323
|
+
const bugbot_mutation_error_1 = __nccwpck_require__(2937);
|
|
2257
2324
|
const pull_request_review_errors_1 = __nccwpck_require__(6445);
|
|
2258
2325
|
async function applyDetectedFindings(operation, context, prepared, publicationPorts, resolutionPorts, catalog) {
|
|
2259
2326
|
try {
|
|
@@ -2269,7 +2336,7 @@ async function applyDetectedFindings(operation, context, prepared, publicationPo
|
|
|
2269
2336
|
});
|
|
2270
2337
|
}
|
|
2271
2338
|
catch (error) {
|
|
2272
|
-
const publicationError = error instanceof pull_request_review_errors_1.PullRequestReviewOperationError
|
|
2339
|
+
const publicationError = error instanceof bugbot_mutation_error_1.BugbotMutationError || error instanceof pull_request_review_errors_1.PullRequestReviewOperationError
|
|
2273
2340
|
? error
|
|
2274
2341
|
: new Error("Unable to publish findings.");
|
|
2275
2342
|
return [publicationError];
|
|
@@ -2540,6 +2607,7 @@ function buildPreviousFindingsContext(previousFindings) {
|
|
|
2540
2607
|
`;
|
|
2541
2608
|
const suffix = `
|
|
2542
2609
|
**Your task 2:** For each finding above, analyze the current code and decide:
|
|
2610
|
+
- Trace the original failure precondition through current callers, validation helpers and effective configuration, including modules outside the original anchor. A retained finding is not proof that its old explanation is still true. Reuse its exact id if reporting the same defect again; do not create a second report for it.
|
|
2543
2611
|
- If the problem **still exists** (same code or same issue present): do **not** include it in \`resolved_findings\`.
|
|
2544
2612
|
- If the problem **no longer applies** (e.g. that code was removed or refactored away): include \`{ "id": "<exact id>", "resolution": "obsolete" }\` in \`resolved_findings\`.
|
|
2545
2613
|
- If the problem **has been fixed** (code was changed and the issue is resolved): include \`{ "id": "<exact id>", "resolution": "fixed" }\` in \`resolved_findings\`.
|
|
@@ -2658,6 +2726,10 @@ function buildReviewConversationContext(issueComments, commentsByPullRequest, bo
|
|
|
2658
2726
|
omitted,
|
|
2659
2727
|
truncated: chronological.filter((entry) => entry.truncated).length,
|
|
2660
2728
|
retained: chronological.length,
|
|
2729
|
+
...(chronological.some(entry => entry.truncated) ? {
|
|
2730
|
+
truncatedItemIds: chronological.filter(entry => entry.truncated)
|
|
2731
|
+
.map(entry => entry.providerId).filter(id => /^(?:issue:[0-9]+|review:[A-Za-z0-9_=-]+)$/.test(id) && id.length <= 160),
|
|
2732
|
+
} : {}),
|
|
2661
2733
|
};
|
|
2662
2734
|
}
|
|
2663
2735
|
function appendConversationEntry(entries, author, kind, body, createdAt, providerId) {
|
|
@@ -3339,6 +3411,7 @@ async function loadBugbotContext(request, ports, resolvedPreflight) {
|
|
|
3339
3411
|
itemsFetched: conversationContext.retained + conversationContext.omitted,
|
|
3340
3412
|
omittedItems: conversationContext.omitted,
|
|
3341
3413
|
truncatedItems: conversationContext.truncated,
|
|
3414
|
+
...(conversationContext.truncatedItemIds ? { truncatedItemIds: conversationContext.truncatedItemIds } : {}),
|
|
3342
3415
|
limitReached: conversationContext.omitted > 0 || conversationContext.truncated > 0,
|
|
3343
3416
|
},
|
|
3344
3417
|
{
|
|
@@ -3537,11 +3610,11 @@ Object.defineProperty(exports, "markFindingsResolved", ({ enumerable: true, get:
|
|
|
3537
3610
|
|
|
3538
3611
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3539
3612
|
exports.markFindingsResolved = markFindingsResolved;
|
|
3540
|
-
const pull_request_review_errors_1 = __nccwpck_require__(6445);
|
|
3541
3613
|
const logging_ports_1 = __nccwpck_require__(6152);
|
|
3542
3614
|
const resolve_issue_finding_1 = __nccwpck_require__(5300);
|
|
3543
3615
|
const resolve_pull_request_finding_1 = __nccwpck_require__(4567);
|
|
3544
3616
|
const review_state_1 = __nccwpck_require__(9200);
|
|
3617
|
+
const bugbot_mutation_error_1 = __nccwpck_require__(2937);
|
|
3545
3618
|
const application_error_1 = __nccwpck_require__(5999);
|
|
3546
3619
|
async function markFindingsResolved(param) {
|
|
3547
3620
|
const errors = [];
|
|
@@ -3569,8 +3642,8 @@ async function repairExistingPullRequestFinding(ports, operation, findingId, des
|
|
|
3569
3642
|
try {
|
|
3570
3643
|
await ports.pullRequestComments.unresolvePullRequestReviewThread(destination.pullRequestNumber, destination.commentIdentity);
|
|
3571
3644
|
}
|
|
3572
|
-
catch {
|
|
3573
|
-
addResolutionError(errors, 'pull request');
|
|
3645
|
+
catch (cause) {
|
|
3646
|
+
addResolutionError(errors, 'pull request', findingId, cause);
|
|
3574
3647
|
}
|
|
3575
3648
|
}
|
|
3576
3649
|
}
|
|
@@ -3584,7 +3657,7 @@ async function resolveIssueIfNeeded(param, findingId, destination, errors) {
|
|
|
3584
3657
|
return;
|
|
3585
3658
|
const comment = param.context.issueComments.find(item => item.id === destination.commentId);
|
|
3586
3659
|
if (comment?.body == null) {
|
|
3587
|
-
addResolutionError(errors, 'issue');
|
|
3660
|
+
addResolutionError(errors, 'issue', findingId);
|
|
3588
3661
|
return;
|
|
3589
3662
|
}
|
|
3590
3663
|
try {
|
|
@@ -3595,8 +3668,8 @@ async function resolveIssueIfNeeded(param, findingId, destination, errors) {
|
|
|
3595
3668
|
resolution: param.resolvedFindingResolutions?.get(findingId),
|
|
3596
3669
|
}, param.catalog);
|
|
3597
3670
|
}
|
|
3598
|
-
catch {
|
|
3599
|
-
addResolutionError(errors, 'issue');
|
|
3671
|
+
catch (cause) {
|
|
3672
|
+
addResolutionError(errors, 'issue', findingId, cause);
|
|
3600
3673
|
}
|
|
3601
3674
|
}
|
|
3602
3675
|
async function tryResolvePullRequestFinding(ports, findingId, destination, errors, resolution, catalog) {
|
|
@@ -3608,17 +3681,14 @@ async function tryResolvePullRequestFinding(ports, findingId, destination, error
|
|
|
3608
3681
|
resolution,
|
|
3609
3682
|
}, catalog);
|
|
3610
3683
|
}
|
|
3611
|
-
catch {
|
|
3612
|
-
addResolutionError(errors, 'pull request');
|
|
3684
|
+
catch (cause) {
|
|
3685
|
+
addResolutionError(errors, 'pull request', findingId, cause);
|
|
3613
3686
|
}
|
|
3614
3687
|
}
|
|
3615
|
-
function addResolutionError(errors, destination) {
|
|
3616
|
-
const
|
|
3617
|
-
?
|
|
3618
|
-
: new
|
|
3619
|
-
const semanticError = new application_error_1.ApplicationError('provider.unavailable', destination === 'pull request'
|
|
3620
|
-
? 'Unable to mark a pull request finding as resolved.'
|
|
3621
|
-
: 'Unable to mark an issue finding as resolved.', { cause });
|
|
3688
|
+
function addResolutionError(errors, destination, findingId, cause) {
|
|
3689
|
+
const semanticError = destination === 'pull request'
|
|
3690
|
+
? (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'resolution', [findingId], 'mark-resolved')
|
|
3691
|
+
: new application_error_1.ApplicationError('provider.unavailable', 'Unable to mark an issue finding as resolved.');
|
|
3622
3692
|
(0, logging_ports_1.logError)(semanticError);
|
|
3623
3693
|
errors.push(semanticError);
|
|
3624
3694
|
}
|
|
@@ -3867,6 +3937,7 @@ function isRecord(value) {
|
|
|
3867
3937
|
*/
|
|
3868
3938
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3869
3939
|
exports.publishFindings = publishFindings;
|
|
3940
|
+
const bugbot_mutation_error_1 = __nccwpck_require__(2937);
|
|
3870
3941
|
const finding_1 = __nccwpck_require__(1011);
|
|
3871
3942
|
const publish_issue_finding_comment_1 = __nccwpck_require__(4950);
|
|
3872
3943
|
const publish_pr_review_comments_1 = __nccwpck_require__(352);
|
|
@@ -3885,12 +3956,17 @@ async function publishFindings(param) {
|
|
|
3885
3956
|
catalog,
|
|
3886
3957
|
})
|
|
3887
3958
|
: undefined;
|
|
3888
|
-
for (const finding of findings) {
|
|
3959
|
+
for (const finding of (0, finding_1.retainExistingFindingIds)(findings, existingByFindingId)) {
|
|
3889
3960
|
if (operation.target.issueNumber > 0 && !reviewPublisher) {
|
|
3890
3961
|
await (0, publish_issue_finding_comment_1.publishIssueFindingComment)(ports.issueComments, operation.target.issueNumber, finding, (0, finding_1.findExistingFindingInfo)(existingByFindingId, finding), commitSha, catalog);
|
|
3891
3962
|
}
|
|
3892
3963
|
if (reviewPublisher) {
|
|
3893
|
-
|
|
3964
|
+
try {
|
|
3965
|
+
await reviewPublisher.publish(finding, (0, finding_1.findExistingFindingInfo)(existingByFindingId, finding));
|
|
3966
|
+
}
|
|
3967
|
+
catch (cause) {
|
|
3968
|
+
throw (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'publication', [finding.id], 'publish-comments');
|
|
3969
|
+
}
|
|
3894
3970
|
}
|
|
3895
3971
|
}
|
|
3896
3972
|
await reviewPublisher?.flush(overflowCount, overflowTitles);
|
|
@@ -3959,6 +4035,7 @@ ${catalog.message('bugbot.overflow.body', { count: `**${overflowCount}**` }, ove
|
|
|
3959
4035
|
|
|
3960
4036
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3961
4037
|
exports.PullRequestReviewCommentPublisher = void 0;
|
|
4038
|
+
const bugbot_mutation_error_1 = __nccwpck_require__(2937);
|
|
3962
4039
|
const bugbot_finding_marker_policy_1 = __nccwpck_require__(8024);
|
|
3963
4040
|
const path_validation_1 = __nccwpck_require__(124);
|
|
3964
4041
|
const logging_ports_1 = __nccwpck_require__(6152);
|
|
@@ -4030,11 +4107,16 @@ class PullRequestReviewCommentPublisher {
|
|
|
4030
4107
|
if (this.findingsToCreate.length === 0 && overflowCount === 0)
|
|
4031
4108
|
return;
|
|
4032
4109
|
const { repository, operation, openPrNumber, prContext } = this.options;
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4110
|
+
try {
|
|
4111
|
+
await repository.createReviewWithComments(openPrNumber, prContext.prHeadSha, buildReviewSummary(this.findingsToCreate, this.commentsToCreate.length, this.unanchoredBodies, overflowCount, overflowTitles, operation.analysis.reviewConfiguration.traceRules
|
|
4112
|
+
? this.options.ruleSources ?? []
|
|
4113
|
+
: [], operation.analysis.reviewConfiguration.traceRules
|
|
4114
|
+
? this.options.omittedRuleCount ?? 0
|
|
4115
|
+
: 0, prContext.prHeadSha, this.catalog), this.commentsToCreate);
|
|
4116
|
+
}
|
|
4117
|
+
catch (cause) {
|
|
4118
|
+
throw (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'publication', this.findingsToCreate.map(finding => finding.id), 'publish-comments', this.findingsToCreate.length + overflowCount);
|
|
4119
|
+
}
|
|
4038
4120
|
}
|
|
4039
4121
|
get catalog() {
|
|
4040
4122
|
return this.options.catalog ?? (0, bugbot_message_catalog_1.resolveStaticBugbotCatalog)(this.options.operation.locale.pullRequest);
|
|
@@ -4188,6 +4270,8 @@ async function queryBugbotPartitionFindings(repository, configuration, prompt, t
|
|
|
4188
4270
|
|
|
4189
4271
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4190
4272
|
exports.reconcileBugbotReviewState = reconcileBugbotReviewState;
|
|
4273
|
+
const bugbot_mutation_error_1 = __nccwpck_require__(2937);
|
|
4274
|
+
const finding_1 = __nccwpck_require__(1011);
|
|
4191
4275
|
const review_projection_1 = __nccwpck_require__(859);
|
|
4192
4276
|
const bugbot_reconciliation_policy_1 = __nccwpck_require__(8128);
|
|
4193
4277
|
const bugbot_provider_projection_policy_1 = __nccwpck_require__(5821);
|
|
@@ -4218,11 +4302,12 @@ async function reconcileBugbotReviewState(input) {
|
|
|
4218
4302
|
};
|
|
4219
4303
|
}
|
|
4220
4304
|
const snapshot = snapshotResult.snapshot;
|
|
4305
|
+
const activeFindings = (0, finding_1.retainExistingFindingIds)(input.activeFindings, input.loadedContext.existingByFindingId);
|
|
4306
|
+
const expectedPublishedFindings = (0, finding_1.retainExistingFindingIds)(input.expectedPublishedFindings ?? input.activeFindings, input.loadedContext.existingByFindingId);
|
|
4221
4307
|
const diagnostics = [
|
|
4222
|
-
...(input.mutationErrors ?? []).map((error) =>
|
|
4223
|
-
code: '
|
|
4224
|
-
operatorMessage: toSafeOperationMessage(error),
|
|
4225
|
-
})),
|
|
4308
|
+
...(input.mutationErrors ?? []).map((error) => error instanceof bugbot_mutation_error_1.BugbotMutationError
|
|
4309
|
+
? { code: 'finding-mutation-failed', mutation: error.diagnostic }
|
|
4310
|
+
: { code: 'operation-failed', operatorMessage: toSafeOperationMessage(error) }),
|
|
4226
4311
|
...(!input.target.trustedAuthorLogin?.trim()
|
|
4227
4312
|
? [{ code: 'identity-unavailable' }]
|
|
4228
4313
|
: []),
|
|
@@ -4231,7 +4316,7 @@ async function reconcileBugbotReviewState(input) {
|
|
|
4231
4316
|
const providerProjection = (0, bugbot_provider_projection_policy_1.projectBugbotProviderEvidence)({
|
|
4232
4317
|
snapshot,
|
|
4233
4318
|
trustedAuthorLogin: input.target.trustedAuthorLogin,
|
|
4234
|
-
activeFindings
|
|
4319
|
+
activeFindings,
|
|
4235
4320
|
existingByFindingId: input.loadedContext.existingByFindingId,
|
|
4236
4321
|
});
|
|
4237
4322
|
const plan = (0, bugbot_reconciliation_policy_1.buildBugbotReconciliationPlan)({
|
|
@@ -4241,8 +4326,8 @@ async function reconcileBugbotReviewState(input) {
|
|
|
4241
4326
|
id,
|
|
4242
4327
|
(0, bugbot_finding_marker_policy_1.extractTitleFromBody)(fullBody) || id,
|
|
4243
4328
|
])),
|
|
4244
|
-
activeFindings
|
|
4245
|
-
expectedPublishedFindings
|
|
4329
|
+
activeFindings,
|
|
4330
|
+
expectedPublishedFindings,
|
|
4246
4331
|
diagnostics,
|
|
4247
4332
|
coverage: input.loadedContext.coverage,
|
|
4248
4333
|
});
|
|
@@ -4697,14 +4782,16 @@ function toPresentationFailure(diagnostic) {
|
|
|
4697
4782
|
const message = (0, bugbot_message_catalog_1.bugbotDiagnosticOperatorMessage)(diagnostic);
|
|
4698
4783
|
return {
|
|
4699
4784
|
diagnostic,
|
|
4700
|
-
error: diagnostic.code === '
|
|
4701
|
-
? new application_error_1.ApplicationError(
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4785
|
+
error: diagnostic.code === 'finding-mutation-failed'
|
|
4786
|
+
? new application_error_1.ApplicationError(diagnostic.mutation.errorCode, message)
|
|
4787
|
+
: diagnostic.code === 'review-updates-pending'
|
|
4788
|
+
? new application_error_1.ApplicationError('workflow.presentation-pending', message, {
|
|
4789
|
+
recovery: {
|
|
4790
|
+
id: 'bugbot-review-blocks-pending',
|
|
4791
|
+
variables: { pendingCount: diagnostic.count },
|
|
4792
|
+
},
|
|
4793
|
+
})
|
|
4794
|
+
: new Error(message),
|
|
4708
4795
|
};
|
|
4709
4796
|
}
|
|
4710
4797
|
function report(projection, reviewUpdates, pendingReviewUpdates, statusCardOperation, errors) {
|
|
@@ -5168,9 +5255,16 @@ exports.APPLICATION_ERROR_RECOVERY_IDS = Object.freeze([
|
|
|
5168
5255
|
'branch-sync-resolution-invalid',
|
|
5169
5256
|
'sdd-draft-size-exceeded',
|
|
5170
5257
|
'sdd-draft-format-invalid',
|
|
5258
|
+
'sdd-draft-case-identity-invalid',
|
|
5259
|
+
'sdd-draft-case-budget-invalid',
|
|
5260
|
+
'sdd-draft-requirement-mapping-invalid',
|
|
5261
|
+
'sdd-draft-repository-path-invalid',
|
|
5171
5262
|
'workspace-changes-rejected',
|
|
5172
5263
|
'closed-issue-reconciliation-failed',
|
|
5173
5264
|
'approval-evidence-read-failed',
|
|
5265
|
+
'stored-configuration-schema-missing',
|
|
5266
|
+
'stored-configuration-schema-unsupported',
|
|
5267
|
+
'stored-configuration-invalid',
|
|
5174
5268
|
]);
|
|
5175
5269
|
const PRESERVED_STATE = 'Existing persisted state and completed external effects were preserved.';
|
|
5176
5270
|
const UNCHANGED_STATE = 'No new state or external effect was created.';
|
|
@@ -5362,6 +5456,9 @@ class ApplicationError extends Error {
|
|
|
5362
5456
|
exports.ApplicationError = ApplicationError;
|
|
5363
5457
|
_ApplicationError_cause = new WeakMap();
|
|
5364
5458
|
const RECOVERY_VARIABLE_KEYS = Object.freeze({
|
|
5459
|
+
'stored-configuration-schema-missing': Object.freeze(['issueNumber', 'expectedVersion']),
|
|
5460
|
+
'stored-configuration-schema-unsupported': Object.freeze(['issueNumber', 'expectedVersion', 'actualVersion']),
|
|
5461
|
+
'stored-configuration-invalid': Object.freeze(['issueNumber', 'expectedVersion']),
|
|
5365
5462
|
'closed-issue-reconciliation-failed': Object.freeze(['resultId', 'phase', 'state', 'reason', 'changed', 'remaining']),
|
|
5366
5463
|
'approval-evidence-read-failed': Object.freeze(['operation', 'reason', 'permission']),
|
|
5367
5464
|
'pull-request-link-restored': Object.freeze([]),
|
|
@@ -5376,6 +5473,10 @@ const RECOVERY_VARIABLE_KEYS = Object.freeze({
|
|
|
5376
5473
|
'branch-sync-resolution-invalid': Object.freeze(['validationCode', 'command']),
|
|
5377
5474
|
'sdd-draft-size-exceeded': Object.freeze([]),
|
|
5378
5475
|
'sdd-draft-format-invalid': Object.freeze([]),
|
|
5476
|
+
'sdd-draft-case-identity-invalid': Object.freeze([]),
|
|
5477
|
+
'sdd-draft-case-budget-invalid': Object.freeze([]),
|
|
5478
|
+
'sdd-draft-requirement-mapping-invalid': Object.freeze([]),
|
|
5479
|
+
'sdd-draft-repository-path-invalid': Object.freeze([]),
|
|
5379
5480
|
'workspace-changes-rejected': Object.freeze([]),
|
|
5380
5481
|
});
|
|
5381
5482
|
function normalizeApplicationErrorRecovery(recovery) {
|
|
@@ -5391,6 +5492,13 @@ function normalizeApplicationErrorRecovery(recovery) {
|
|
|
5391
5492
|
|| actualKeys.some((key, index) => key !== expectedKeys[index])) {
|
|
5392
5493
|
throw new TypeError(`Application error recovery variables are invalid for ${recovery.id}.`);
|
|
5393
5494
|
}
|
|
5495
|
+
if (recovery.id.startsWith('stored-configuration-')
|
|
5496
|
+
&& (![variables.issueNumber, variables.expectedVersion].every(value => typeof value === 'number' && Number.isSafeInteger(value) && value > 0)
|
|
5497
|
+
|| (recovery.id === 'stored-configuration-schema-unsupported'
|
|
5498
|
+
&& !(typeof variables.actualVersion === 'number'
|
|
5499
|
+
&& Number.isSafeInteger(variables.actualVersion) && variables.actualVersion >= 0)))) {
|
|
5500
|
+
throw new TypeError('Stored configuration diagnostic is invalid.');
|
|
5501
|
+
}
|
|
5394
5502
|
if (recovery.id === 'managed-branch-enrichment-failed'
|
|
5395
5503
|
&& (typeof variables.branchName !== 'string'
|
|
5396
5504
|
|| !/^[A-Za-z0-9][A-Za-z0-9._/-]{0,254}$/u.test(variables.branchName))) {
|
|
@@ -5642,9 +5750,14 @@ function matchesConstrainedHead(target, candidate) {
|
|
|
5642
5750
|
/***/ }),
|
|
5643
5751
|
|
|
5644
5752
|
/***/ 1011:
|
|
5645
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
5753
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5646
5754
|
|
|
5647
5755
|
|
|
5756
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
5757
|
+
exports.isExistingFindingFullyResolved = isExistingFindingFullyResolved;
|
|
5758
|
+
exports.findExistingFindingInfo = findExistingFindingInfo;
|
|
5759
|
+
exports.findExistingFindingMatch = findExistingFindingMatch;
|
|
5760
|
+
exports.retainExistingFindingIds = retainExistingFindingIds;
|
|
5648
5761
|
/**
|
|
5649
5762
|
* Provider-neutral Bugbot finding and durable identity contracts.
|
|
5650
5763
|
*
|
|
@@ -5652,9 +5765,7 @@ function matchesConstrainedHead(target, candidate) {
|
|
|
5652
5765
|
* them in the domain prevents policies from depending on a particular use-case
|
|
5653
5766
|
* folder and gives every adapter one stable semantic vocabulary.
|
|
5654
5767
|
*/
|
|
5655
|
-
|
|
5656
|
-
exports.isExistingFindingFullyResolved = isExistingFindingFullyResolved;
|
|
5657
|
-
exports.findExistingFindingInfo = findExistingFindingInfo;
|
|
5768
|
+
const finding_identity_1 = __nccwpck_require__(1853);
|
|
5658
5769
|
function isExistingFindingFullyResolved(finding) {
|
|
5659
5770
|
const destinations = [finding.issue, finding.pullRequest].filter((destination) => destination != null);
|
|
5660
5771
|
return (destinations.length > 0 &&
|
|
@@ -5662,21 +5773,62 @@ function isExistingFindingFullyResolved(finding) {
|
|
|
5662
5773
|
finding.pullRequest?.verificationRequired !== true);
|
|
5663
5774
|
}
|
|
5664
5775
|
function findExistingFindingInfo(existingByFindingId, finding) {
|
|
5776
|
+
return findExistingFindingMatch(existingByFindingId, finding)?.info;
|
|
5777
|
+
}
|
|
5778
|
+
/** A match carries its durable key so updating a comment cannot re-key it. */
|
|
5779
|
+
function findExistingFindingMatch(existingByFindingId, finding) {
|
|
5665
5780
|
const direct = existingByFindingId[finding.id];
|
|
5666
5781
|
if (direct && identitiesAreCompatible(direct, finding))
|
|
5667
|
-
return direct;
|
|
5668
|
-
const candidates = Object.
|
|
5782
|
+
return { id: finding.id, info: direct };
|
|
5783
|
+
const candidates = Object.entries(existingByFindingId);
|
|
5669
5784
|
if (finding.fingerprint) {
|
|
5670
|
-
const
|
|
5785
|
+
const locationMatches = candidates.filter(([, candidate]) => candidate.issue?.fingerprint === finding.fingerprint
|
|
5671
5786
|
|| candidate.pullRequest?.fingerprint === finding.fingerprint);
|
|
5672
|
-
if (
|
|
5673
|
-
return
|
|
5787
|
+
if (locationMatches.length > 0)
|
|
5788
|
+
return uniqueFindingMatch(locationMatches);
|
|
5674
5789
|
}
|
|
5675
5790
|
if (!finding.semanticFingerprint)
|
|
5676
5791
|
return undefined;
|
|
5677
|
-
const semanticMatches = candidates.filter((candidate) => candidate.issue?.semanticFingerprint === finding.semanticFingerprint
|
|
5792
|
+
const semanticMatches = candidates.filter(([, candidate]) => candidate.issue?.semanticFingerprint === finding.semanticFingerprint
|
|
5678
5793
|
|| candidate.pullRequest?.semanticFingerprint === finding.semanticFingerprint);
|
|
5679
|
-
return semanticMatches
|
|
5794
|
+
return uniqueFindingMatch(semanticMatches);
|
|
5795
|
+
}
|
|
5796
|
+
/**
|
|
5797
|
+
* Preserve trusted IDs across title/location changes, before limits, publication
|
|
5798
|
+
* and final projection. Multiple reports of one uniquely matched durable finding
|
|
5799
|
+
* share one record; unmatched or ambiguous reports remain independent evidence.
|
|
5800
|
+
*/
|
|
5801
|
+
function retainExistingFindingIds(findings, existingByFindingId) {
|
|
5802
|
+
const retained = new Set();
|
|
5803
|
+
const durableIds = new Set(Object.keys(existingByFindingId));
|
|
5804
|
+
// Reserve the whole input up front so a generated ID cannot take another
|
|
5805
|
+
// report's ID, including one that occurs later in the response.
|
|
5806
|
+
const reservedIds = new Set([...durableIds, ...findings.map((finding) => finding.id)]);
|
|
5807
|
+
const emittedIds = new Set();
|
|
5808
|
+
return findings.flatMap((finding) => {
|
|
5809
|
+
const match = findExistingFindingMatch(existingByFindingId, finding);
|
|
5810
|
+
if (!match) {
|
|
5811
|
+
let id = finding.id;
|
|
5812
|
+
if (durableIds.has(id) || emittedIds.has(id)) {
|
|
5813
|
+
const base = `candidate-${(0, finding_identity_1.buildFindingFingerprint)(finding)}`;
|
|
5814
|
+
id = base;
|
|
5815
|
+
let suffix = 0;
|
|
5816
|
+
while (reservedIds.has(id))
|
|
5817
|
+
id = `${base}-${++suffix}`;
|
|
5818
|
+
reservedIds.add(id);
|
|
5819
|
+
}
|
|
5820
|
+
emittedIds.add(id);
|
|
5821
|
+
return [id === finding.id ? finding : { ...finding, id }];
|
|
5822
|
+
}
|
|
5823
|
+
if (retained.has(match.id))
|
|
5824
|
+
return [];
|
|
5825
|
+
retained.add(match.id);
|
|
5826
|
+
emittedIds.add(match.id);
|
|
5827
|
+
return [finding.id === match.id ? finding : { ...finding, id: match.id }];
|
|
5828
|
+
});
|
|
5829
|
+
}
|
|
5830
|
+
function uniqueFindingMatch(matches) {
|
|
5831
|
+
return matches.length === 1 ? { id: matches[0][0], info: matches[0][1] } : undefined;
|
|
5680
5832
|
}
|
|
5681
5833
|
function identitiesAreCompatible(existing, finding) {
|
|
5682
5834
|
const existingFingerprints = [
|
|
@@ -6539,11 +6691,13 @@ function getAnswerIssueHelpPrompt(params) {
|
|
|
6539
6691
|
|
|
6540
6692
|
|
|
6541
6693
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6694
|
+
exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION = void 0;
|
|
6542
6695
|
exports.getBugbotPrompt = getBugbotPrompt;
|
|
6543
6696
|
/**
|
|
6544
6697
|
* Prompt for Bugbot detection (detect potential problems on push).
|
|
6545
6698
|
*/
|
|
6546
6699
|
const fill_1 = __nccwpck_require__(2559);
|
|
6700
|
+
exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION = 'Before returning a finding, try to disprove it against the exact reviewed source. Read effective repository configuration and inherited library/protocol defaults before inferring behavior from a missing command flag. Trace short-circuit guards, validation helpers and the actual caller/render path before claiming that an unsafe branch is reachable or that separate call sites coexist. Recompute arithmetic and check cited line numbers against the current file/diff. If your evidence refutes the alleged defect, withdraw the finding entirely; do not publish a contradictory or self-refuting report. These checks apply equally to low/info severity. Report a confirmed failure when those protections are absent; do not assume they exist.';
|
|
6547
6701
|
const TEMPLATE = `You are analyzing the latest code changes for potential bugs and issues.
|
|
6548
6702
|
|
|
6549
6703
|
Write every human-readable finding title, description, evidence, and suggestion in {{targetLocale}}. Preserve identifiers, code, symbols, paths, refs, commands, and URLs verbatim. Echo \`outputLocale\` exactly as \`{{targetLocale}}\`.
|
|
@@ -6579,6 +6733,8 @@ For every finding:
|
|
|
6579
6733
|
- include the nearest stable \`symbol\` and a minimal exact \`codeSnippet\` when available so the finding can survive rebases, line movement, and file renames.
|
|
6580
6734
|
- when a fix is a safe replacement of exactly the reported line range, include only the replacement text in \`suggestedCode\`; otherwise omit it.
|
|
6581
6735
|
|
|
6736
|
+
${exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION}
|
|
6737
|
+
|
|
6582
6738
|
Return every finding field required by the response schema. Use null for file, line, endLine, severity, confidence, category, evidence, suggestion, symbol, codeSnippet, or suggestedCode when that value does not safely apply. Only include files outside the ignore list.
|
|
6583
6739
|
{{previousBlock}}
|
|
6584
6740
|
|
|
@@ -3,9 +3,22 @@ import { type ApprovalEvidenceDiagnostic } from '../../domain/approval_evidence_
|
|
|
3
3
|
import { type BranchSyncValidationCode } from '../../domain/branch_sync_validation';
|
|
4
4
|
export type ApplicationErrorKind = 'configuration' | 'authorization' | 'provider' | 'agent' | 'validation' | 'workflow' | 'unknown';
|
|
5
5
|
export type ApplicationErrorCode = 'configuration.invalid' | 'configuration.unsupported' | 'authorization.denied' | 'authorization.credential-invalid' | 'provider.not-found' | 'provider.conflict' | 'provider.rate-limited' | 'provider.unavailable' | 'provider.contract-invalid' | 'agent.policy-rejected' | 'agent.failed' | 'locale.output-invalid' | 'locale.translation-failed' | 'validation.invalid-input' | 'validation.evidence-too-large' | 'validation.evidence-unavailable' | 'workflow.invalid-event' | 'workflow.stale' | 'workflow.cancelled' | 'workflow.failed' | 'workflow.presentation-pending' | 'timeout' | 'unexpected';
|
|
6
|
-
export declare const APPLICATION_ERROR_RECOVERY_IDS: readonly ["pull-request-link-restored", "pull-request-link-base-retained", "pull-request-link-reference-retained", "pull-request-link-base-and-reference-retained", "managed-branch-enrichment-failed", "inactivity-explanation-failed", "bugbot-review-blocks-pending", "branch-sync-agent-disabled", "branch-sync-fixer-unavailable", "branch-sync-resolution-invalid", "sdd-draft-size-exceeded", "sdd-draft-format-invalid", "workspace-changes-rejected", "closed-issue-reconciliation-failed", "approval-evidence-read-failed"];
|
|
6
|
+
export declare const APPLICATION_ERROR_RECOVERY_IDS: readonly ["pull-request-link-restored", "pull-request-link-base-retained", "pull-request-link-reference-retained", "pull-request-link-base-and-reference-retained", "managed-branch-enrichment-failed", "inactivity-explanation-failed", "bugbot-review-blocks-pending", "branch-sync-agent-disabled", "branch-sync-fixer-unavailable", "branch-sync-resolution-invalid", "sdd-draft-size-exceeded", "sdd-draft-format-invalid", "sdd-draft-case-identity-invalid", "sdd-draft-case-budget-invalid", "sdd-draft-requirement-mapping-invalid", "sdd-draft-repository-path-invalid", "workspace-changes-rejected", "closed-issue-reconciliation-failed", "approval-evidence-read-failed", "stored-configuration-schema-missing", "stored-configuration-schema-unsupported", "stored-configuration-invalid"];
|
|
7
7
|
export type ApplicationErrorRecoveryId = typeof APPLICATION_ERROR_RECOVERY_IDS[number];
|
|
8
8
|
interface ApplicationErrorRecoveryVariables {
|
|
9
|
+
readonly 'stored-configuration-schema-missing': Readonly<{
|
|
10
|
+
issueNumber: number;
|
|
11
|
+
expectedVersion: number;
|
|
12
|
+
}>;
|
|
13
|
+
readonly 'stored-configuration-schema-unsupported': Readonly<{
|
|
14
|
+
issueNumber: number;
|
|
15
|
+
expectedVersion: number;
|
|
16
|
+
actualVersion: number;
|
|
17
|
+
}>;
|
|
18
|
+
readonly 'stored-configuration-invalid': Readonly<{
|
|
19
|
+
issueNumber: number;
|
|
20
|
+
expectedVersion: number;
|
|
21
|
+
}>;
|
|
9
22
|
readonly 'closed-issue-reconciliation-failed': ClosedIssueReconciliationFacts;
|
|
10
23
|
readonly 'approval-evidence-read-failed': ApprovalEvidenceDiagnostic;
|
|
11
24
|
readonly 'pull-request-link-restored': Readonly<Record<string, never>>;
|
|
@@ -33,6 +46,10 @@ interface ApplicationErrorRecoveryVariables {
|
|
|
33
46
|
}>;
|
|
34
47
|
readonly 'sdd-draft-size-exceeded': Readonly<Record<string, never>>;
|
|
35
48
|
readonly 'sdd-draft-format-invalid': Readonly<Record<string, never>>;
|
|
49
|
+
readonly 'sdd-draft-case-identity-invalid': Readonly<Record<string, never>>;
|
|
50
|
+
readonly 'sdd-draft-case-budget-invalid': Readonly<Record<string, never>>;
|
|
51
|
+
readonly 'sdd-draft-requirement-mapping-invalid': Readonly<Record<string, never>>;
|
|
52
|
+
readonly 'sdd-draft-repository-path-invalid': Readonly<Record<string, never>>;
|
|
36
53
|
readonly 'workspace-changes-rejected': Readonly<Record<string, never>>;
|
|
37
54
|
}
|
|
38
55
|
export type ApplicationErrorRecovery = {
|
|
@@ -8,6 +8,8 @@ export interface BugbotSourceCoverage {
|
|
|
8
8
|
readonly itemsRetained: number;
|
|
9
9
|
readonly omittedItems: number;
|
|
10
10
|
readonly truncatedItems: number;
|
|
11
|
+
/** Exact bounded provider identities of retained conversation items truncated by the prompt. */
|
|
12
|
+
readonly truncatedItemIds?: readonly string[];
|
|
11
13
|
readonly limitReached: boolean;
|
|
12
14
|
/** True when a provider page cap hides an unknown number of older records. */
|
|
13
15
|
readonly providerLimitReached?: boolean;
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider-neutral Bugbot finding and durable identity contracts.
|
|
3
|
-
*
|
|
4
|
-
* These types are shared by analysis, reconciliation, and publication. Keeping
|
|
5
|
-
* them in the domain prevents policies from depending on a particular use-case
|
|
6
|
-
* folder and gives every adapter one stable semantic vocabulary.
|
|
7
|
-
*/
|
|
8
1
|
export interface BugbotFinding {
|
|
9
2
|
id: string;
|
|
10
3
|
title: string;
|
|
@@ -59,3 +52,14 @@ export interface ExistingFindingInfo {
|
|
|
59
52
|
export type ExistingByFindingId = Record<string, ExistingFindingInfo>;
|
|
60
53
|
export declare function isExistingFindingFullyResolved(finding: ExistingFindingInfo): boolean;
|
|
61
54
|
export declare function findExistingFindingInfo(existingByFindingId: ExistingByFindingId, finding: Pick<BugbotFinding, 'id' | 'fingerprint' | 'semanticFingerprint'>): ExistingFindingInfo | undefined;
|
|
55
|
+
/** A match carries its durable key so updating a comment cannot re-key it. */
|
|
56
|
+
export declare function findExistingFindingMatch(existingByFindingId: ExistingByFindingId, finding: Pick<BugbotFinding, 'id' | 'fingerprint' | 'semanticFingerprint'>): {
|
|
57
|
+
id: string;
|
|
58
|
+
info: ExistingFindingInfo;
|
|
59
|
+
} | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Preserve trusted IDs across title/location changes, before limits, publication
|
|
62
|
+
* and final projection. Multiple reports of one uniquely matched durable finding
|
|
63
|
+
* share one record; unmatched or ambiguous reports remain independent evidence.
|
|
64
|
+
*/
|
|
65
|
+
export declare function retainExistingFindingIds(findings: readonly BugbotFinding[], existingByFindingId: ExistingByFindingId): BugbotFinding[];
|