@vypdev/copilot 3.9.1 → 3.9.3

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.
@@ -38189,6 +38189,8 @@ var __importStar = (this && this.__importStar) || (function () {
38189
38189
  })();
38190
38190
  Object.defineProperty(exports, "__esModule", ({ value: true }));
38191
38191
  exports.runPullRequestApprovalAction = runPullRequestApprovalAction;
38192
+ const application_error_presentation_policy_1 = __nccwpck_require__(95067);
38193
+ const application_error_message_catalog_1 = __nccwpck_require__(64809);
38192
38194
  const core = __importStar(__nccwpck_require__(75855));
38193
38195
  const github = __importStar(__nccwpck_require__(78227));
38194
38196
  const observe_pull_request_approval_use_case_1 = __nccwpck_require__(36169);
@@ -38238,15 +38240,22 @@ async function runPullRequestApprovalAction(token) {
38238
38240
  });
38239
38241
  const useCase = new observe_pull_request_approval_use_case_1.ObservePullRequestApprovalUseCase(port);
38240
38242
  const failedPulls = [];
38243
+ let firstFailure;
38241
38244
  for (const pullNumber of targetNumbers) {
38242
38245
  const target = { owner, repository: repo, repositoryId, pullNumber };
38243
38246
  const result = await useCase.execute(target);
38247
+ if (result.failure) {
38248
+ firstFailure ?? (firstFailure = result.failure);
38249
+ const diagnostic = (0, application_error_presentation_policy_1.renderApplicationErrorText)(result.failure, (0, application_error_message_catalog_1.resolveStaticApplicationErrorCatalog)(locale).message);
38250
+ core.info(diagnostic);
38251
+ core.summary.addRaw(`<pre>${diagnostic.replace(/&/gu, '&amp;').replace(/</gu, '&lt;').replace(/>/gu, '&gt;')}</pre>\n`);
38252
+ }
38244
38253
  const safeCode = result.decision.code.replace(/[^a-z0-9-]/gu, '').slice(0, 60);
38245
38254
  core.info(`PR #${pullNumber}: ${result.decision.status} (${safeCode}); assessment ${result.publication}.`);
38246
38255
  if (result.publication === 'failed' || [
38247
38256
  'invalid-policy', 'policy-unavailable', 'evidence-unavailable', 'target-mismatch',
38248
38257
  'pre-submit-unavailable', 'publication-unknown',
38249
- ].includes(result.decision.code))
38258
+ ].includes(result.decision.code) || result.failure)
38250
38259
  failedPulls.push(pullNumber);
38251
38260
  if (result.evidence) {
38252
38261
  core.summary.addRaw((0, pull_request_approval_presentation_policy_1.renderApprovalRunSummary)({
@@ -38267,6 +38276,8 @@ async function runPullRequestApprovalAction(token) {
38267
38276
  }
38268
38277
  }
38269
38278
  await core.summary.write();
38279
+ if (firstFailure)
38280
+ throw firstFailure;
38270
38281
  if (failedPulls.length > 0) {
38271
38282
  throw new Error(`Approval observation needs attention for PR(s) ${failedPulls.join(', ')}; inspect the Job Summary and rerun after recovery.`);
38272
38283
  }
@@ -38816,6 +38827,55 @@ function runAtApplicationErrorBoundary(operation) {
38816
38827
  }
38817
38828
 
38818
38829
 
38830
+ /***/ }),
38831
+
38832
+ /***/ 50519:
38833
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
38834
+
38835
+ "use strict";
38836
+
38837
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
38838
+ exports.approvalEvidenceError = approvalEvidenceError;
38839
+ exports.approvalDiagnosticError = approvalDiagnosticError;
38840
+ const approval_evidence_diagnostic_1 = __nccwpck_require__(98205);
38841
+ const application_error_1 = __nccwpck_require__(75999);
38842
+ function approvalEvidenceError(operation, reason) {
38843
+ return approvalDiagnosticError({ operation, reason, permission: approval_evidence_diagnostic_1.APPROVAL_EVIDENCE_PERMISSIONS[operation] });
38844
+ }
38845
+ function approvalDiagnosticError(diagnostic) {
38846
+ const reason = diagnostic.reason;
38847
+ const code = reason === 'http-401' ? 'authorization.credential-invalid'
38848
+ : reason === 'http-403' ? 'authorization.denied'
38849
+ : reason === 'http-404' ? 'provider.not-found'
38850
+ : reason === 'http-429' ? 'provider.rate-limited'
38851
+ : reason === 'http-409' ? 'provider.conflict'
38852
+ : reason === 'transport-unavailable' || /^http-50[0234]$/u.test(reason) ? 'provider.unavailable'
38853
+ : 'provider.contract-invalid';
38854
+ return new application_error_1.ApplicationError(code, `Approval evidence read failed (${diagnostic.operation}, ${reason}).`, {
38855
+ recovery: { id: 'approval-evidence-read-failed', variables: diagnostic },
38856
+ });
38857
+ }
38858
+
38859
+
38860
+ /***/ }),
38861
+
38862
+ /***/ 12183:
38863
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
38864
+
38865
+ "use strict";
38866
+
38867
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
38868
+ exports.closedIssueReconciliationError = closedIssueReconciliationError;
38869
+ const application_error_1 = __nccwpck_require__(75999);
38870
+ /** Public diagnostic is fixed native facts and counters, never label/card/provider text. */
38871
+ function closedIssueReconciliationError(cause, facts) {
38872
+ return new application_error_1.ApplicationError(cause instanceof application_error_1.ApplicationError ? cause.code : 'provider.unavailable', 'Closed issue reconciliation remains unverified.', {
38873
+ ...(cause instanceof application_error_1.ApplicationError ? { correlationId: cause.correlationId, retryable: cause.retryable } : {}),
38874
+ recovery: { id: 'closed-issue-reconciliation-failed', variables: facts },
38875
+ });
38876
+ }
38877
+
38878
+
38819
38879
  /***/ }),
38820
38880
 
38821
38881
  /***/ 72594:
@@ -38854,7 +38914,7 @@ const application_error_message_catalog_1 = __nccwpck_require__(64809);
38854
38914
  const SIMPLE_MESSAGE_KEYS = Object.freeze([
38855
38915
  'heading', 'repository', 'property', 'value', 'status', 'event', 'target',
38856
38916
  'lifecycle', 'descriptionPolicy', 'results', 'findingStates', 'bugbotReview',
38857
- 'inactivity', 'unavailable',
38917
+ 'inactivity', 'unavailable', 'issueCleanup',
38858
38918
  'sourceFreshness', 'staleSourceSuppressed',
38859
38919
  'duplicateCleanup', 'actionNotifications', 'actionNotificationCreated',
38860
38920
  'actionNotificationReused',
@@ -38876,6 +38936,7 @@ const TEMPLATE_MESSAGE_IDS = Object.freeze([
38876
38936
  'summary.duplicateCleanup.bounded',
38877
38937
  'summary.actionNotification.entry',
38878
38938
  'summary.inactivityCounts',
38939
+ 'summary.issueCleanupCounts',
38879
38940
  ]);
38880
38941
  const FINDING_STATE_KEYS = Object.freeze([
38881
38942
  'open', 'reopened', 'fixed', 'obsolete', 'dismissed',
@@ -38899,6 +38960,7 @@ const ENGLISH_SIMPLE = Object.freeze({
38899
38960
  descriptionPolicy: 'PR description policy',
38900
38961
  results: 'Results',
38901
38962
  inactivity: 'Issue inactivity',
38963
+ issueCleanup: 'Issue cleanup',
38902
38964
  unavailable: 'unavailable',
38903
38965
  findingStates: 'Finding states',
38904
38966
  bugbotReview: 'Bugbot review',
@@ -38948,6 +39010,7 @@ const SPANISH_SIMPLE = Object.freeze({
38948
39010
  descriptionPolicy: 'Política de descripción de PR',
38949
39011
  results: 'Resultados',
38950
39012
  inactivity: 'Inactividad de issues',
39013
+ issueCleanup: 'Limpieza de la issue',
38951
39014
  unavailable: 'no disponible',
38952
39015
  findingStates: 'Estados de los hallazgos',
38953
39016
  bugbotReview: 'Revisión de Bugbot',
@@ -38995,6 +39058,7 @@ const ENGLISH_TEMPLATES = Object.freeze({
38995
39058
  'summary.duplicateCleanup.bounded': 'Deletion was forbidden; retained compact pointers for {count} comments (first {reported} IDs: {ids})',
38996
39059
  'summary.actionNotification.entry': '{topic} on {target}: {effect} (fingerprint {fingerprint})',
38997
39060
  'summary.inactivityCounts': 'Scanned: {scanned} · Closed: {closed} · Skipped: {skipped}',
39061
+ 'summary.issueCleanupCounts': 'Reconciled: {reconciled} · Already converged: {converged}. Required cleanup was freshly verified.',
38998
39062
  });
38999
39063
  const SPANISH_TEMPLATES = Object.freeze({
39000
39064
  'summary.target.pullRequest': 'PR n.º {number}',
@@ -39006,6 +39070,7 @@ const SPANISH_TEMPLATES = Object.freeze({
39006
39070
  'summary.duplicateCleanup.bounded': 'Se denegó el borrado; se conservaron enlaces compactos para {count} comentarios (primeros {reported} ID: {ids})',
39007
39071
  'summary.actionNotification.entry': '{topic} en {target}: {effect} (huella {fingerprint})',
39008
39072
  'summary.inactivityCounts': 'Examinadas: {scanned} · Cerradas: {closed} · Omitidas: {skipped}',
39073
+ 'summary.issueCleanupCounts': 'Reconciliadas: {reconciled} · Ya convergidas: {converged}. Se verificó de nuevo la limpieza necesaria.',
39009
39074
  });
39010
39075
  const ENGLISH_FINDING_STATES = Object.freeze({
39011
39076
  open: 'open',
@@ -39068,6 +39133,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
39068
39133
  exports.buildActionSummary = buildActionSummary;
39069
39134
  exports.actionSummaryLocalizationLabels = actionSummaryLocalizationLabels;
39070
39135
  exports.renderLocalizationSummarySection = renderLocalizationSummarySection;
39136
+ const closed_issue_reconciliation_outcome_policy_1 = __nccwpck_require__(85462);
39071
39137
  const inactivity_result_counts_projection_policy_1 = __nccwpck_require__(14960);
39072
39138
  const github_comment_publication_policy_1 = __nccwpck_require__(72712);
39073
39139
  const bugbot_telemetry_projection_policy_1 = __nccwpck_require__(43244);
@@ -39117,6 +39183,7 @@ function buildActionSummary(context, catalog = (0, action_summary_message_catalo
39117
39183
  `| ${catalogText(catalog, 'summary.descriptionPolicy')} | ${escapeTable(context.pullRequestDescriptionMode ?? '—')} |`,
39118
39184
  `| ${catalogText(catalog, 'summary.results')} | ${formatResultCounts(context.results, catalog)} |`,
39119
39185
  ...inactivitySummaryRows(context.results, catalog),
39186
+ ...closedIssueCleanupRows(context.results, catalog),
39120
39187
  `| ${catalogText(catalog, 'summary.findingStates')} | ${formatFindingStates(findingStateProjection, catalog)} |`,
39121
39188
  `| ${catalogText(catalog, 'summary.bugbotReview')} | ${formatBugbotTelemetry(telemetryProjection, catalog)} |`,
39122
39189
  ...(staleSourceSuppressed ? [
@@ -39147,6 +39214,14 @@ function buildActionSummary(context, catalog = (0, action_summary_message_catalo
39147
39214
  ...(localization ? ['', localization] : []),
39148
39215
  ].join('\n');
39149
39216
  }
39217
+ function closedIssueCleanupRows(results, catalog) {
39218
+ const projection = (0, closed_issue_reconciliation_outcome_policy_1.projectClosedIssueCleanupCounts)(results);
39219
+ if (projection.status === 'absent')
39220
+ return [];
39221
+ const value = projection.status === 'valid' ? catalogText(catalog, 'summary.issueCleanupCounts', projection.counts)
39222
+ : catalogText(catalog, 'summary.unavailable');
39223
+ return [`| ${catalogText(catalog, 'summary.issueCleanup')} | ${value} |`];
39224
+ }
39150
39225
  function inactivitySummaryRows(results, catalog) {
39151
39226
  const projection = (0, inactivity_result_counts_projection_policy_1.projectInactivityResultCounts)(results);
39152
39227
  if (projection.status === 'absent')
@@ -40592,6 +40667,16 @@ const SPANISH_CONTENT = Object.freeze({
40592
40667
  }),
40593
40668
  });
40594
40669
  const ENGLISH_RECOVERY_CONTENT = Object.freeze({
40670
+ 'closed-issue-reconciliation-failed': Object.freeze({
40671
+ impact: 'Issue cleanup remains unverified: {resultId}, phase {phase}; native state {state}, reason {reason}.',
40672
+ action: 'Inspect the closed-issue or merged-PR run and current native state. Retry cleanup only if the issue is still closed with the intended reason; leave reopened work open. Resolve the named failure before retrying.',
40673
+ retainedState: 'Native state was preserved. Confirmed changes: {changed}; remaining required changes in the last verified plan: {remaining}. Unavailable reads do not establish completion.',
40674
+ }),
40675
+ 'approval-evidence-read-failed': Object.freeze({
40676
+ impact: 'Approval evidence could not be verified: {operation} ({reason}).',
40677
+ action: 'Inspect {permission} access for the runtime credential and the named evidence response. Correct authorization, missing-resource or schema errors before rerunning; retry transient failures only after provider recovery or rate-limit reset.',
40678
+ retainedState: 'No approval is authorized by this failed read. Existing PRs, reviews and completed external effects were preserved.',
40679
+ }),
40595
40680
  'workspace-changes-rejected': Object.freeze({
40596
40681
  impact: 'The changes were rejected during workspace verification.',
40597
40682
  action: 'Inspect the rejected paths in the workflow and correct the workspace before retrying.',
@@ -40659,6 +40744,16 @@ const ENGLISH_RECOVERY_CONTENT = Object.freeze({
40659
40744
  }),
40660
40745
  });
40661
40746
  const SPANISH_RECOVERY_CONTENT = Object.freeze({
40747
+ 'closed-issue-reconciliation-failed': Object.freeze({
40748
+ impact: 'La limpieza de la issue sigue sin verificarse: {resultId}, fase {phase}; estado nativo {state}, motivo {reason}.',
40749
+ action: 'Revisa la ejecución de cierre o de la PR fusionada y el estado nativo actual. Reintenta la limpieza solo si la issue sigue cerrada con el motivo previsto; conserva abierto el trabajo reabierto. Resuelve el fallo indicado antes de reintentar.',
40750
+ retainedState: 'Se conservó el estado nativo. Cambios confirmados: {changed}; cambios pendientes en el último plan verificado: {remaining}. Una lectura no disponible no demuestra que haya finalizado.',
40751
+ }),
40752
+ 'approval-evidence-read-failed': Object.freeze({
40753
+ impact: 'No se pudo verificar la evidencia de aprobación: {operation} ({reason}).',
40754
+ action: 'Comprueba el acceso {permission} de la credencial de ejecución y la respuesta indicada. Corrige los errores de autorización, recurso o esquema antes de reejecutar; reintenta los fallos transitorios solo tras recuperarse el proveedor o restablecerse el límite.',
40755
+ retainedState: 'Esta lectura fallida no autoriza ninguna aprobación. Se conservaron las PRs, revisiones y efectos externos completados.',
40756
+ }),
40662
40757
  'workspace-changes-rejected': Object.freeze({
40663
40758
  impact: 'Los cambios se rechazaron durante la verificación del espacio de trabajo.',
40664
40759
  action: 'Revisa las rutas rechazadas en la ejecución y corrige el espacio de trabajo antes de reintentar.',
@@ -42877,6 +42972,51 @@ function hasBugbotTelemetryField(value) {
42877
42972
  }
42878
42973
 
42879
42974
 
42975
+ /***/ }),
42976
+
42977
+ /***/ 85462:
42978
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
42979
+
42980
+ "use strict";
42981
+
42982
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
42983
+ exports.projectClosedIssueCleanupCounts = projectClosedIssueCleanupCounts;
42984
+ const result_1 = __nccwpck_require__(73817);
42985
+ const closed_issue_reconciliation_1 = __nccwpck_require__(21565);
42986
+ /** Summary consumes semantic counts; internal result identifiers never become presentation. */
42987
+ function projectClosedIssueCleanupCounts(results) {
42988
+ let reconciled = 0;
42989
+ let converged = 0;
42990
+ let invalid = false;
42991
+ for (const result of results.filter(result => closed_issue_reconciliation_1.CLOSED_ISSUE_RESULTS.some(id => id === result.id))) {
42992
+ const payload = (0, result_1.getResultPayload)(result.payload);
42993
+ if (!result.success || result.errors?.length) {
42994
+ invalid = true;
42995
+ continue;
42996
+ }
42997
+ if (!payload)
42998
+ continue;
42999
+ const completion = result.id === 'CloseIssueAfterMergingUseCase' || result.id === 'ReconcileClosedIssueMetadataUseCase'
43000
+ ? (0, result_1.getResultPayload)(payload.issueCompletion) : payload;
43001
+ if (completion?.outcome === 'not-applicable' && completion.nativeClosed === false)
43002
+ continue;
43003
+ if (completion?.nativeClosed !== true || completion.reconciled !== true) {
43004
+ invalid = true;
43005
+ continue;
43006
+ }
43007
+ if (completion.outcome === 'already-converged')
43008
+ converged++;
43009
+ else if (completion.outcome === 'reconciled')
43010
+ reconciled++;
43011
+ else
43012
+ invalid = true;
43013
+ }
43014
+ if (!invalid && !reconciled && !converged)
43015
+ return { status: 'absent' };
43016
+ return invalid ? { status: 'invalid' } : { status: 'valid', counts: { reconciled, converged } };
43017
+ }
43018
+
43019
+
42880
43020
  /***/ }),
42881
43021
 
42882
43022
  /***/ 27150:
@@ -47341,6 +47481,34 @@ function verifiedReadinessLink(snapshot, number) {
47341
47481
  }
47342
47482
 
47343
47483
 
47484
+ /***/ }),
47485
+
47486
+ /***/ 59756:
47487
+ /***/ ((__unused_webpack_module, exports) => {
47488
+
47489
+ "use strict";
47490
+
47491
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
47492
+ exports.hasConventionalPullRequestTitle = hasConventionalPullRequestTitle;
47493
+ exports.generatedPullRequestTitle = generatedPullRequestTitle;
47494
+ /** Recognizes the conventional header shape; the consumer's CI owns its allowed types and subject rules. */
47495
+ function hasConventionalPullRequestTitle(title) {
47496
+ return !title.includes('\n') && !title.includes('\r')
47497
+ && /^\p{L}[\p{L}\p{N}_-]*(?:\([^()\r\n]+\))?!?: +\S[^\r\n]*$/u.test(title);
47498
+ }
47499
+ function generatedPullRequestTitle(sourceTitle, sanitizedSubject, issueNumber, labels) {
47500
+ if (hasConventionalPullRequestTitle(sourceTitle))
47501
+ return sourceTitle;
47502
+ const type = labels.isHotfix || labels.isBugfix || labels.isBug ? 'fix'
47503
+ : labels.isFeature || labels.isEnhancement ? 'feat'
47504
+ : labels.isDocs || labels.isDocumentation ? 'docs' : 'chore';
47505
+ const prefix = `${type}: `;
47506
+ const suffix = ` (#${issueNumber})`;
47507
+ const subject = (sanitizedSubject || 'Update linked issue').slice(0, 256 - prefix.length - suffix.length).trimEnd();
47508
+ return `${prefix}${subject}${suffix}`;
47509
+ }
47510
+
47511
+
47344
47512
  /***/ }),
47345
47513
 
47346
47514
  /***/ 39410:
@@ -47532,6 +47700,12 @@ Do not add the \`${profile.deployment.launcherLabel}\` label, dispatch a deploym
47532
47700
 
47533
47701
  Never expose credentials, tokens, private keys, or other secrets in issues, commits, pull requests, logs, or diagnostic comments.
47534
47702
 
47703
+ ## Repository verification prerequisites
47704
+
47705
+ The setup runner profile selects placement; it does not install the project's language runtimes. An operator must provision the project's required runtimes and dependencies in every job that runs file-changing or branch-sync verification, before the Copilot step. A separate application CI job does not prepare this job.
47706
+
47707
+ Declare reviewed version prefixes in \`.copilot/verification-prerequisites.json\` (schemaVersion 1, runtimes such as java 17, node 24, pnpm 10). Copilot checks declared versions in the credential-free verification environment before each configured verification command; a missing or incompatible runtime blocks publication. Without this optional declaration, existing verification behavior remains and no language is inferred. Java provisioning may use \`actions/setup-java\`; \`JAVA_HOME\` and \`PATH\` survive isolation, while agent credentials and tool-option injection variables do not. Do not add an unreviewed bootstrap or weaken verification to work around a missing runtime. Read [verification prerequisites and same-job setup](https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites).
47708
+
47535
47709
  For the full contributor flow, read [repository collaboration](https://github.com/vypdev/copilot/blob/master/docs/agents/repository-collaboration.mdx). For drift and recovery, read [guidance troubleshooting](https://github.com/vypdev/copilot/blob/master/docs/agents/repository-guidance-troubleshooting.mdx).
47536
47710
  `;
47537
47711
  }
@@ -50738,6 +50912,87 @@ function projectCurrentNativeStatus(status, facts) {
50738
50912
  }
50739
50913
 
50740
50914
 
50915
+ /***/ }),
50916
+
50917
+ /***/ 89347:
50918
+ /***/ ((__unused_webpack_module, exports) => {
50919
+
50920
+ "use strict";
50921
+
50922
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
50923
+ exports.VerificationPrerequisiteError = exports.VERIFICATION_RUNTIME_SPECS = exports.VERIFICATION_RUNTIME_HELP = exports.VERIFICATION_RUNTIME_MANIFEST = void 0;
50924
+ exports.parseVerificationRuntimeManifest = parseVerificationRuntimeManifest;
50925
+ exports.verificationRuntimeVersion = verificationRuntimeVersion;
50926
+ exports.verificationRuntimeMatches = verificationRuntimeMatches;
50927
+ exports.VERIFICATION_RUNTIME_MANIFEST = '.copilot/verification-prerequisites.json';
50928
+ exports.VERIFICATION_RUNTIME_HELP = 'https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites';
50929
+ exports.VERIFICATION_RUNTIME_SPECS = {
50930
+ java: { label: 'Java', program: 'java', args: ['-version'] },
50931
+ node: { label: 'Node.js', program: 'node', args: ['--version'] },
50932
+ pnpm: { label: 'pnpm', program: 'pnpm', args: ['--version'] },
50933
+ python: { label: 'Python', program: 'python3', args: ['--version'] },
50934
+ go: { label: 'Go', program: 'go', args: ['version'] },
50935
+ dotnet: { label: '.NET SDK', program: 'dotnet', args: ['--version'] },
50936
+ ruby: { label: 'Ruby', program: 'ruby', args: ['--version'] },
50937
+ rust: { label: 'Rust', program: 'rustc', args: ['--version'] },
50938
+ };
50939
+ const VERSION_PREFIX = /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,2}$/u;
50940
+ /** Only reviewed, closed runtime/version facts enter user-visible diagnostics. Raw tool output never does. */
50941
+ class VerificationPrerequisiteError extends Error {
50942
+ constructor(reason, requirement, observed, job) {
50943
+ const jobLabel = job && /^[A-Za-z_][A-Za-z0-9_-]{0,99}$/u.test(job) ? ` in job ${job}` : ' in this job';
50944
+ const runtime = requirement && Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, requirement.runtime)
50945
+ ? exports.VERIFICATION_RUNTIME_SPECS[requirement.runtime].label : 'Required runtime';
50946
+ const version = requirement && VERSION_PREFIX.test(requirement.version) ? requirement.version : 'declared version';
50947
+ const actual = observed && /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,3}$/u.test(observed) ? observed : 'unavailable';
50948
+ const cause = reason === 'manifest-invalid' ? `${exports.VERIFICATION_RUNTIME_MANIFEST} is invalid or unsafe`
50949
+ : reason === 'version-mismatch' ? `${runtime} ${version} is required; observed ${actual}`
50950
+ : reason === 'unreadable-version' ? `${runtime} ${version} could not be verified`
50951
+ : `${runtime} ${version} is unavailable`;
50952
+ const action = reason === 'manifest-invalid' ? 'Correct the reviewed runtime declaration.'
50953
+ : `Provision the declared runtime in the same job before Copilot, then retry.${requirement?.runtime === 'java' ? ' For Java, configure actions/setup-java or a managed JAVA_HOME.' : ''}`;
50954
+ super(`Repository verification is blocked${jobLabel}: ${cause}. ${action} The repository verification command was not run. Help: ${exports.VERIFICATION_RUNTIME_HELP}`);
50955
+ this.name = 'VerificationPrerequisiteError';
50956
+ }
50957
+ }
50958
+ exports.VerificationPrerequisiteError = VerificationPrerequisiteError;
50959
+ function parseVerificationRuntimeManifest(value) {
50960
+ if (!value || typeof value !== 'object' || Array.isArray(value))
50961
+ throw new VerificationPrerequisiteError('manifest-invalid');
50962
+ const object = value;
50963
+ if (object.schemaVersion !== 1 || Object.keys(object).some(key => !['schemaVersion', 'runtimes'].includes(key))
50964
+ || !object.runtimes || typeof object.runtimes !== 'object' || Array.isArray(object.runtimes)) {
50965
+ throw new VerificationPrerequisiteError('manifest-invalid');
50966
+ }
50967
+ const runtimes = object.runtimes;
50968
+ if (Object.keys(runtimes).length > 8)
50969
+ throw new VerificationPrerequisiteError('manifest-invalid');
50970
+ return Object.entries(runtimes).map(([runtime, version]) => {
50971
+ if (!Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, runtime) || typeof version !== 'string' || !VERSION_PREFIX.test(version)) {
50972
+ throw new VerificationPrerequisiteError('manifest-invalid');
50973
+ }
50974
+ return Object.freeze({ runtime: runtime, version });
50975
+ });
50976
+ }
50977
+ function verificationRuntimeVersion(runtime, output) {
50978
+ const patterns = {
50979
+ java: /^(?:openjdk|java) (?:version )?["']?(\d+(?:\.\d+){0,3})/imu,
50980
+ node: /^v(\d+\.\d+\.\d+)/mu,
50981
+ pnpm: /^(\d+\.\d+\.\d+)/mu,
50982
+ python: /^Python (\d+\.\d+\.\d+)/mu,
50983
+ go: /^go version go(\d+\.\d+(?:\.\d+)?)/mu,
50984
+ dotnet: /^(\d+\.\d+\.\d+)/mu,
50985
+ ruby: /^ruby (\d+\.\d+\.\d+)/mu,
50986
+ rust: /^rustc (\d+\.\d+\.\d+)/mu,
50987
+ };
50988
+ const version = patterns[runtime].exec(output)?.[1];
50989
+ return runtime === 'java' && version?.startsWith('1.') ? version.slice(2) : version;
50990
+ }
50991
+ function verificationRuntimeMatches(required, observed) {
50992
+ return observed === required || observed.startsWith(`${required}.`);
50993
+ }
50994
+
50995
+
50741
50996
  /***/ }),
50742
50997
 
50743
50998
  /***/ 43193:
@@ -53947,8 +54202,9 @@ function failure(taskId, message, code) {
53947
54202
  Object.defineProperty(exports, "__esModule", ({ value: true }));
53948
54203
  exports.ReconcileClosedIssueMetadataUseCase = void 0;
53949
54204
  const result_1 = __nccwpck_require__(73817);
53950
- const issue_completion_1 = __nccwpck_require__(31147);
53951
54205
  const application_error_1 = __nccwpck_require__(75999);
54206
+ const closed_issue_reconciliation_error_1 = __nccwpck_require__(12183);
54207
+ const reconcile_issue_completion_metadata_1 = __nccwpck_require__(70614);
53952
54208
  /** Selective completion repair from fresh native facts; no native state authority. */
53953
54209
  class ReconcileClosedIssueMetadataUseCase {
53954
54210
  constructor(issues) {
@@ -53956,50 +54212,22 @@ class ReconcileClosedIssueMetadataUseCase {
53956
54212
  this.taskId = 'ReconcileClosedIssueMetadataUseCase';
53957
54213
  }
53958
54214
  async invoke(context) {
53959
- let labelsChanged = 0;
53960
- let nativeClosed = false;
54215
+ const progress = (0, reconcile_issue_completion_metadata_1.completionRepairProgress)();
53961
54216
  try {
53962
54217
  if (!Number.isSafeInteger(context.issueNumber) || context.issueNumber < 1)
53963
54218
  throw stale();
53964
54219
  const target = this.issues.forIssue(context.issueNumber);
53965
- const initial = await target.read();
53966
- nativeClosed = initial.number === context.issueNumber && initial.state === 'closed';
53967
- const initialPlan = (0, issue_completion_1.planIssueCompletion)(initial, context.completionLabels);
53968
- if (!nativeClosed || initialPlan.kind !== 'closed')
53969
- throw stale();
53970
- const fence = async () => {
53971
- const current = await target.read();
53972
- nativeClosed = current.number === context.issueNumber && current.state === 'closed';
53973
- const plan = (0, issue_completion_1.planIssueCompletion)(current, context.completionLabels);
53974
- if (!nativeClosed || plan.kind !== 'closed' || current.reason !== initial.reason)
53975
- throw stale();
53976
- return plan;
53977
- };
53978
- for (const label of initialPlan.remove) {
53979
- if ((await fence()).remove.includes(label)) {
53980
- await target.removeLabel(label);
53981
- labelsChanged++;
53982
- }
53983
- }
53984
- for (const label of initialPlan.add) {
53985
- if ((await fence()).add.includes(label)) {
53986
- await target.addLabel(label);
53987
- labelsChanged++;
53988
- }
53989
- }
53990
- const final = await fence();
53991
- if (final.remove.length || final.add.length)
53992
- throw stale();
53993
- return [new result_1.Result({ id: this.taskId, success: true, executed: labelsChanged > 0,
54220
+ const repaired = await (0, reconcile_issue_completion_metadata_1.reconcileIssueCompletionMetadata)(target, context.issueNumber, context.completionLabels, progress);
54221
+ return [new result_1.Result({ id: this.taskId, success: true, executed: progress.labelsChanged > 0,
53994
54222
  steps: ['The closed issue completion metadata was verified; historical and unrelated labels were retained.'],
53995
- payload: { issueCompletion: { nativeClosed, labelsChanged, reconciled: true, reason: initial.reason } } })];
54223
+ payload: { issueCompletion: { nativeClosed: progress.nativeClosed, labelsChanged: progress.labelsChanged, reconciled: true, ...repaired } } })];
53996
54224
  }
53997
54225
  catch (cause) {
53998
- return [new result_1.Result({ id: this.taskId, success: false, executed: labelsChanged > 0,
53999
- steps: [nativeClosed ? 'The issue remains closed; completion metadata could not be fully verified. Inspect and retry the closed-issue workflow.'
54226
+ return [new result_1.Result({ id: this.taskId, success: false, executed: progress.labelsChanged > 0,
54227
+ steps: [progress.nativeClosed ? 'The issue remains closed; completion metadata could not be fully verified. Inspect and retry the closed-issue workflow.'
54000
54228
  : 'Current native issue closure could not be verified; completion repair stopped without changing native state.'],
54001
- errors: [(0, application_error_1.toApplicationError)(cause, 'provider.unavailable', 'Closed issue completion metadata remains unverified.')],
54002
- payload: { issueCompletion: { nativeClosed, labelsChanged, reconciled: false } } })];
54229
+ errors: [(0, closed_issue_reconciliation_error_1.closedIssueReconciliationError)(cause, { resultId: this.taskId, phase: progress.phase, state: progress.state, reason: progress.reason, changed: progress.labelsChanged, remaining: progress.remaining })],
54230
+ payload: { issueCompletion: { nativeClosed: progress.nativeClosed, labelsChanged: progress.labelsChanged, reconciled: false } } })];
54003
54231
  }
54004
54232
  }
54005
54233
  }
@@ -54032,6 +54260,84 @@ class ReconcileClosedIssueUseCase {
54032
54260
  exports.ReconcileClosedIssueUseCase = ReconcileClosedIssueUseCase;
54033
54261
 
54034
54262
 
54263
+ /***/ }),
54264
+
54265
+ /***/ 70614:
54266
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
54267
+
54268
+ "use strict";
54269
+
54270
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
54271
+ exports.completionRepairProgress = void 0;
54272
+ exports.reconcileIssueCompletionMetadata = reconcileIssueCompletionMetadata;
54273
+ const application_error_1 = __nccwpck_require__(75999);
54274
+ const issue_completion_1 = __nccwpck_require__(31147);
54275
+ const closed_issue_reconciliation_1 = __nccwpck_require__(21565);
54276
+ const completionRepairProgress = () => ({ nativeClosed: false, labelsChanged: 0,
54277
+ phase: 'identity', state: 'unavailable', reason: 'unavailable', remaining: 0 });
54278
+ exports.completionRepairProgress = completionRepairProgress;
54279
+ /** At most two bounded selective passes, with fresh native fences before every write. */
54280
+ async function reconcileIssueCompletionMetadata(target, number, configuration, progress, initial) {
54281
+ let expectedReason;
54282
+ let superseded = false;
54283
+ const read = async (phase, snapshot) => {
54284
+ progress.phase = phase;
54285
+ progress.state = 'unavailable';
54286
+ progress.reason = 'unavailable';
54287
+ const facts = snapshot ?? await target.read();
54288
+ progress.nativeClosed = facts?.number === number && facts.state === 'closed';
54289
+ progress.state = facts?.number === number && ['open', 'closed'].includes(facts.state) ? facts.state : 'unavailable';
54290
+ progress.reason = closed_issue_reconciliation_1.CLOSED_ISSUE_REASONS.some(reason => reason === facts?.reason) ? facts.reason : 'unavailable';
54291
+ const plan = (0, issue_completion_1.planIssueCompletion)(facts, configuration);
54292
+ if (!progress.nativeClosed || plan.kind !== 'closed' || expectedReason !== undefined && facts.reason !== expectedReason) {
54293
+ throw new application_error_1.ApplicationError('workflow.stale', 'The native issue identity, state or closure reason changed.');
54294
+ }
54295
+ expectedReason = facts.reason;
54296
+ progress.remaining = plan.remove.length + plan.add.length;
54297
+ return plan;
54298
+ };
54299
+ let plan = await read('read', initial);
54300
+ for (let pass = 0; pass < 2; pass++) {
54301
+ for (const label of plan.remove) {
54302
+ if (!(await read('label-remove')).remove.includes(label)) {
54303
+ superseded = true;
54304
+ continue;
54305
+ }
54306
+ try {
54307
+ await target.removeLabel(label);
54308
+ progress.labelsChanged++;
54309
+ }
54310
+ catch (cause) {
54311
+ if ((await read('label-remove')).remove.includes(label))
54312
+ throw cause;
54313
+ superseded = true;
54314
+ }
54315
+ }
54316
+ for (const label of plan.add) {
54317
+ if (!(await read('label-add')).add.includes(label)) {
54318
+ superseded = true;
54319
+ continue;
54320
+ }
54321
+ try {
54322
+ await target.addLabel(label);
54323
+ progress.labelsChanged++;
54324
+ }
54325
+ catch (cause) {
54326
+ if ((await read('label-add')).add.includes(label))
54327
+ throw cause;
54328
+ superseded = true;
54329
+ }
54330
+ }
54331
+ plan = await read('metadata-verification');
54332
+ if (!progress.remaining)
54333
+ return { reason: plan.reason,
54334
+ outcome: progress.labelsChanged ? 'reconciled' : 'already-converged', superseded };
54335
+ superseded = true;
54336
+ }
54337
+ throw new application_error_1.ApplicationError('provider.conflict', 'Completion metadata remains incomplete after two bounded passes.');
54338
+ }
54339
+
54340
+
54035
54341
  /***/ }),
54036
54342
 
54037
54343
  /***/ 74111:
@@ -54041,7 +54347,9 @@ exports.ReconcileClosedIssueUseCase = ReconcileClosedIssueUseCase;
54041
54347
 
54042
54348
  Object.defineProperty(exports, "__esModule", ({ value: true }));
54043
54349
  exports.RetireBranchSyncUseCase = void 0;
54044
- const reply_request_digest_1 = __nccwpck_require__(47971);
54350
+ const verify_closed_issue_card_retirement_1 = __nccwpck_require__(78813);
54351
+ const closed_issue_reconciliation_error_1 = __nccwpck_require__(12183);
54352
+ const closed_issue_reconciliation_1 = __nccwpck_require__(21565);
54045
54353
  const result_1 = __nccwpck_require__(73817);
54046
54354
  const github_user_policy_1 = __nccwpck_require__(84403);
54047
54355
  const publication_identity_policy_1 = __nccwpck_require__(45403);
@@ -54059,17 +54367,33 @@ class RetireBranchSyncUseCase {
54059
54367
  async invoke(context) {
54060
54368
  let retired = 0;
54061
54369
  let nativeClosed = false;
54370
+ let phase = 'identity';
54371
+ let state = 'unavailable';
54372
+ let reason = 'unavailable';
54373
+ let remaining = 0;
54374
+ let superseded = false;
54062
54375
  try {
54063
54376
  if (!Number.isSafeInteger(context.issueNumber) || context.issueNumber < 1 || !context.trustedBotLogin) {
54064
54377
  return [this.result(retired, nativeClosed)];
54065
54378
  }
54066
- const initial = await this.issues.readIssue(context.issueNumber);
54067
- if (initial.number !== context.issueNumber || !['open', 'closed'].includes(initial.state))
54379
+ const read = async () => {
54380
+ state = 'unavailable';
54381
+ reason = 'unavailable';
54382
+ const facts = await this.issues.readIssue(context.issueNumber);
54383
+ nativeClosed = facts?.number === context.issueNumber && facts.state === 'closed';
54384
+ state = facts?.number === context.issueNumber && ['open', 'closed'].includes(facts.state) ? facts.state : 'unavailable';
54385
+ reason = closed_issue_reconciliation_1.CLOSED_ISSUE_REASONS.some(value => value === facts?.reason) ? facts.reason : 'unavailable';
54386
+ return facts;
54387
+ };
54388
+ phase = 'read';
54389
+ const initial = await read();
54390
+ if (initial.number !== context.issueNumber || !['open', 'closed'].includes(initial.state) || initial.state === 'closed' && !['completed', 'not_planned', 'duplicate', 'unknown'].includes(initial.reason))
54068
54391
  throw stale();
54069
54392
  if (initial.state !== 'closed')
54070
54393
  return [this.result(retired, nativeClosed)];
54071
54394
  nativeClosed = true;
54072
54395
  const messages = (0, branch_sync_message_catalog_1.resolveStaticBranchSyncCatalog)(context.locale);
54396
+ phase = 'card-inventory';
54073
54397
  const cards = (await this.comments.listIssueComments(context.issueNumber)).filter(comment => {
54074
54398
  const marker = (0, publication_identity_policy_1.parsePublicationMarker)(comment.body);
54075
54399
  return marker?.identity.topic === 'branch-sync' && marker.identity.target.kind === 'issue'
@@ -54078,38 +54402,40 @@ class RetireBranchSyncUseCase {
54078
54402
  && Number.isSafeInteger(comment.id) && comment.id > 0
54079
54403
  && Boolean(comment.user?.login && (0, github_user_policy_1.githubUsersMatch)(context.trustedBotLogin, comment.user.login));
54080
54404
  });
54405
+ remaining = Math.min(cards.length, 3000);
54081
54406
  if (cards.length > 20)
54082
54407
  throw stale();
54408
+ const verifyClosed = async () => {
54409
+ phase = 'native-fence';
54410
+ const fresh = await read();
54411
+ if (!nativeClosed || fresh.reason !== initial.reason)
54412
+ throw stale();
54413
+ };
54083
54414
  for (const card of cards) {
54084
54415
  const marker = (0, publication_identity_policy_1.parsePublicationMarker)(card.body);
54085
54416
  const body = (0, branch_sync_notification_policy_1.buildRetiredBranchSyncComment)(marker.identity, messages);
54086
- if (card.body === body)
54087
- continue;
54088
- const witness = Object.freeze({ surface: 'issue-comment', commentId: card.id,
54089
- author: context.trustedBotLogin, target: Object.freeze({ kind: 'issue', number: context.issueNumber }),
54090
- bodyDigest: (0, reply_request_digest_1.replyRequestBodyDigest)(card.body ?? '') });
54091
- if (!await this.cardFreshness.matches(witness))
54092
- throw stale();
54093
- const fresh = await this.issues.readIssue(context.issueNumber);
54094
- nativeClosed = fresh.number === context.issueNumber && fresh.state === 'closed';
54095
- if (!nativeClosed || fresh.reason !== initial.reason)
54096
- throw stale();
54097
- await this.comments.updateComment(context.issueNumber, card.id, body);
54098
- retired++;
54417
+ const verified = await (0, verify_closed_issue_card_retirement_1.verifyClosedIssueCardRetirement)({ issueNumber: context.issueNumber,
54418
+ commentId: card.id, author: context.trustedBotLogin, originalBody: card.body ?? '', finalBody: body,
54419
+ freshness: this.cardFreshness, verifyClosed, onUpdated: () => { retired++; }, phase: value => { phase = value; },
54420
+ update: () => this.comments.updateComment(context.issueNumber, card.id, body) });
54421
+ superseded || (superseded = verified.superseded);
54422
+ remaining--;
54099
54423
  }
54100
- return [this.result(retired, nativeClosed)];
54424
+ await verifyClosed();
54425
+ return [this.result(retired, nativeClosed, superseded)];
54101
54426
  }
54102
54427
  catch (cause) {
54103
54428
  return [new result_1.Result({ id: this.taskId, success: false, executed: retired > 0,
54104
54429
  steps: [nativeClosed ? 'Issue closure is retained; synchronization recommendation retirement could not be fully verified. Retry the closed-issue event or merged-PR operation.' : 'Native issue closure could not be verified; synchronization recommendations were left unchanged.'],
54105
- errors: [(0, application_error_1.toApplicationError)(cause, 'provider.unavailable', 'Unable to retire synchronization recommendations safely.')],
54430
+ errors: [(0, closed_issue_reconciliation_error_1.closedIssueReconciliationError)(cause, { resultId: this.taskId, phase, state, reason, changed: retired, remaining })],
54106
54431
  payload: { nativeClosed, retiredCards: retired, reconciled: false } })];
54107
54432
  }
54108
54433
  }
54109
- result(retired, nativeClosed) {
54434
+ result(retired, nativeClosed, superseded = false) {
54110
54435
  return new result_1.Result({ id: this.taskId, success: true, executed: retired > 0,
54111
54436
  steps: [retired ? 'The closed issue’s synchronization recommendations were retired.' : 'No synchronization recommendation required retirement.'],
54112
- payload: { ...(nativeClosed ? { state: 'closed' } : {}), nativeClosed, retiredCards: retired, reconciled: true } });
54437
+ payload: { ...(nativeClosed ? { state: 'closed' } : {}), nativeClosed, retiredCards: retired, reconciled: true, superseded,
54438
+ outcome: nativeClosed ? retired ? 'reconciled' : 'already-converged' : 'not-applicable' } });
54113
54439
  }
54114
54440
  }
54115
54441
  exports.RetireBranchSyncUseCase = RetireBranchSyncUseCase;
@@ -54150,7 +54476,9 @@ exports.RetireClosedIssueCardsUseCase = RetireClosedIssueCardsUseCase;
54150
54476
 
54151
54477
  Object.defineProperty(exports, "__esModule", ({ value: true }));
54152
54478
  exports.RetireProgressUseCase = void 0;
54153
- const reply_request_digest_1 = __nccwpck_require__(47971);
54479
+ const verify_closed_issue_card_retirement_1 = __nccwpck_require__(78813);
54480
+ const closed_issue_reconciliation_error_1 = __nccwpck_require__(12183);
54481
+ const closed_issue_reconciliation_1 = __nccwpck_require__(21565);
54154
54482
  const result_1 = __nccwpck_require__(73817);
54155
54483
  const github_user_policy_1 = __nccwpck_require__(84403);
54156
54484
  const publication_identity_policy_1 = __nccwpck_require__(45403);
@@ -54167,16 +54495,32 @@ class RetireProgressUseCase {
54167
54495
  async invoke(context) {
54168
54496
  let retired = 0;
54169
54497
  let nativeClosed = false;
54498
+ let phase = 'identity';
54499
+ let state = 'unavailable';
54500
+ let reason = 'unavailable';
54501
+ let remaining = 0;
54502
+ let superseded = false;
54170
54503
  try {
54171
54504
  if (!Number.isSafeInteger(context.issueNumber) || context.issueNumber < 1 || !context.trustedBotLogin) {
54172
54505
  return [this.result(retired, nativeClosed)];
54173
54506
  }
54174
- const initial = await this.issues.readIssue(context.issueNumber);
54507
+ const read = async () => {
54508
+ state = 'unavailable';
54509
+ reason = 'unavailable';
54510
+ const facts = await this.issues.readIssue(context.issueNumber);
54511
+ nativeClosed = facts?.number === context.issueNumber && facts.state === 'closed';
54512
+ state = facts?.number === context.issueNumber && ['open', 'closed'].includes(facts.state) ? facts.state : 'unavailable';
54513
+ reason = closed_issue_reconciliation_1.CLOSED_ISSUE_REASONS.some(value => value === facts?.reason) ? facts.reason : 'unavailable';
54514
+ return facts;
54515
+ };
54516
+ phase = 'read';
54517
+ const initial = await read();
54175
54518
  if (initial.number !== context.issueNumber || !['open', 'closed'].includes(initial.state) || initial.state === 'closed' && !['completed', 'not_planned', 'duplicate', 'unknown'].includes(initial.reason))
54176
54519
  throw stale();
54177
54520
  if (initial.state !== 'closed')
54178
54521
  return [this.result(retired, nativeClosed)];
54179
54522
  nativeClosed = true;
54523
+ phase = 'card-inventory';
54180
54524
  const cards = (await this.comments.listIssueComments(context.issueNumber)).filter(comment => {
54181
54525
  const marker = (0, publication_identity_policy_1.parsePublicationMarker)(comment.body);
54182
54526
  return marker?.identity.topic === 'progress' && marker.identity.target.kind === 'issue'
@@ -54185,37 +54529,39 @@ class RetireProgressUseCase {
54185
54529
  && Number.isSafeInteger(comment.id) && comment.id > 0
54186
54530
  && Boolean(comment.user?.login && (0, github_user_policy_1.githubUsersMatch)(context.trustedBotLogin, comment.user.login));
54187
54531
  });
54532
+ remaining = Math.min(cards.length, 3000);
54188
54533
  if (cards.length > 20)
54189
54534
  throw stale();
54190
- for (const card of cards) {
54191
- const body = (0, retired_progress_presentation_policy_1.buildRetiredProgressComment)(card.body ?? '', context.locale, initial.reason);
54192
- if (card.body === body)
54193
- continue;
54194
- const witness = Object.freeze({ surface: 'issue-comment', commentId: card.id,
54195
- author: context.trustedBotLogin, target: Object.freeze({ kind: 'issue', number: context.issueNumber }),
54196
- bodyDigest: (0, reply_request_digest_1.replyRequestBodyDigest)(card.body ?? '') });
54197
- if (!await this.cardFreshness.matches(witness))
54198
- throw stale();
54199
- const fresh = await this.issues.readIssue(context.issueNumber);
54200
- nativeClosed = fresh.number === context.issueNumber && fresh.state === 'closed';
54535
+ const verifyClosed = async () => {
54536
+ phase = 'native-fence';
54537
+ const fresh = await read();
54201
54538
  if (!nativeClosed || fresh.reason !== initial.reason)
54202
54539
  throw stale();
54203
- await this.comments.updateComment(context.issueNumber, card.id, body);
54204
- retired++;
54540
+ };
54541
+ for (const card of cards) {
54542
+ const body = (0, retired_progress_presentation_policy_1.buildRetiredProgressComment)(card.body ?? '', context.locale, initial.reason);
54543
+ const verified = await (0, verify_closed_issue_card_retirement_1.verifyClosedIssueCardRetirement)({ issueNumber: context.issueNumber,
54544
+ commentId: card.id, author: context.trustedBotLogin, originalBody: card.body ?? '', finalBody: body,
54545
+ freshness: this.cardFreshness, verifyClosed, onUpdated: () => { retired++; }, phase: value => { phase = value; },
54546
+ update: () => this.comments.updateComment(context.issueNumber, card.id, body) });
54547
+ superseded || (superseded = verified.superseded);
54548
+ remaining--;
54205
54549
  }
54206
- return [this.result(retired, nativeClosed)];
54550
+ await verifyClosed();
54551
+ return [this.result(retired, nativeClosed, superseded)];
54207
54552
  }
54208
54553
  catch (cause) {
54209
54554
  return [new result_1.Result({ id: this.taskId, success: false, executed: retired > 0,
54210
54555
  steps: [nativeClosed ? 'Issue closure is retained; progress card retirement could not be fully verified. Retry the closed-issue event or merged-PR operation.' : 'Native issue closure could not be verified; progress cards were left unchanged.'],
54211
- errors: [(0, application_error_1.toApplicationError)(cause, 'provider.unavailable', 'Unable to retire progress cards safely.')],
54556
+ errors: [(0, closed_issue_reconciliation_error_1.closedIssueReconciliationError)(cause, { resultId: this.taskId, phase, state, reason, changed: retired, remaining })],
54212
54557
  payload: { nativeClosed, retiredCards: retired, reconciled: false } })];
54213
54558
  }
54214
54559
  }
54215
- result(retired, nativeClosed) {
54560
+ result(retired, nativeClosed, superseded = false) {
54216
54561
  return new result_1.Result({ id: this.taskId, success: true, executed: retired > 0,
54217
54562
  steps: [retired ? 'The closed issue’s progress cards were retired.' : 'No progress card required retirement.'],
54218
- payload: { ...(nativeClosed ? { state: 'closed' } : {}), nativeClosed, retiredCards: retired, reconciled: true } });
54563
+ payload: { ...(nativeClosed ? { state: 'closed' } : {}), nativeClosed, retiredCards: retired, reconciled: true, superseded,
54564
+ outcome: nativeClosed ? retired ? 'reconciled' : 'already-converged' : 'not-applicable' } });
54219
54565
  }
54220
54566
  }
54221
54567
  exports.RetireProgressUseCase = RetireProgressUseCase;
@@ -54738,6 +55084,48 @@ function sameLabels(left, right) {
54738
55084
  }
54739
55085
 
54740
55086
 
55087
+ /***/ }),
55088
+
55089
+ /***/ 78813:
55090
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
55091
+
55092
+ "use strict";
55093
+
55094
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
55095
+ exports.verifyClosedIssueCardRetirement = verifyClosedIssueCardRetirement;
55096
+ const reply_request_digest_1 = __nccwpck_require__(47971);
55097
+ const application_error_1 = __nccwpck_require__(75999);
55098
+ /** Adopt another invocation only after the exact final owned body and native closure are fresh. */
55099
+ async function verifyClosedIssueCardRetirement(input) {
55100
+ const witness = (body) => Object.freeze({ surface: 'issue-comment',
55101
+ commentId: input.commentId, author: input.author,
55102
+ target: Object.freeze({ kind: 'issue', number: input.issueNumber }), bodyDigest: (0, reply_request_digest_1.replyRequestBodyDigest)(body) });
55103
+ let updated = false;
55104
+ let failedWrite;
55105
+ if (input.originalBody !== input.finalBody) {
55106
+ input.phase('card-freshness');
55107
+ if (await input.freshness.matches(witness(input.originalBody))) {
55108
+ await input.verifyClosed();
55109
+ input.phase('card-update');
55110
+ try {
55111
+ await input.update();
55112
+ updated = true;
55113
+ input.onUpdated();
55114
+ }
55115
+ catch (cause) {
55116
+ failedWrite = cause;
55117
+ }
55118
+ }
55119
+ }
55120
+ input.phase('card-verification');
55121
+ if (!await input.freshness.matches(witness(input.finalBody))) {
55122
+ throw failedWrite ?? new application_error_1.ApplicationError('workflow.stale', 'The required final owned card could not be verified.');
55123
+ }
55124
+ await input.verifyClosed();
55125
+ return { updated, superseded: !updated && input.originalBody !== input.finalBody };
55126
+ }
55127
+
55128
+
54741
55129
  /***/ }),
54742
55130
 
54743
55131
  /***/ 4643:
@@ -54965,7 +55353,7 @@ class SyncBranchUseCase {
54965
55353
  const commands = (0, verify_command_policy_1.limitVerifyCommands)([...context.verifyCommands]);
54966
55354
  if (commands.length === verify_command_policy_1.MAX_VERIFY_COMMANDS)
54967
55355
  (0, logging_ports_1.logInfo)(`Branch sync verification is capped at ${verify_command_policy_1.MAX_VERIFY_COMMANDS} commands.`);
54968
- const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true }));
55356
+ const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
54969
55357
  if (!verification.success) {
54970
55358
  return {
54971
55359
  commandCount: commands.length,
@@ -57082,6 +57470,8 @@ function buildCatalogResponseSchema(source, ids, targetLocale = 'en-US') {
57082
57470
 
57083
57471
  Object.defineProperty(exports, "__esModule", ({ value: true }));
57084
57472
  exports.ObservePullRequestApprovalUseCase = void 0;
57473
+ const application_error_1 = __nccwpck_require__(75999);
57474
+ const approval_evidence_error_1 = __nccwpck_require__(50519);
57085
57475
  const pull_request_approval_1 = __nccwpck_require__(8024);
57086
57476
  const pull_request_approval_policy_1 = __nccwpck_require__(98820);
57087
57477
  /** Read-first replay and exact-revision guard around the non-atomic GitHub review API. */
@@ -57095,8 +57485,9 @@ class ObservePullRequestApprovalUseCase {
57095
57485
  try {
57096
57486
  rawPolicy = await this.port.readPolicy(target);
57097
57487
  }
57098
- catch {
57488
+ catch (cause) {
57099
57489
  return {
57490
+ failure: evidenceFailure(cause, 'policy'),
57100
57491
  decision: { status: 'blocked', code: 'policy-unavailable', detail: 'The installed PR approval policy could not be read from GitHub. Verify the runtime PAT can read Actions Variables, then rerun the observer. Existing PRs and reviews are unchanged.' },
57101
57492
  publication: 'not-applicable',
57102
57493
  };
@@ -57117,8 +57508,9 @@ class ObservePullRequestApprovalUseCase {
57117
57508
  try {
57118
57509
  initial = await this.port.loadEvidence(target);
57119
57510
  }
57120
- catch {
57511
+ catch (cause) {
57121
57512
  return {
57513
+ failure: evidenceFailure(cause),
57122
57514
  decision: { status: 'blocked', code: 'evidence-unavailable', detail: 'GitHub approval evidence could not be read; rerun this observer.' },
57123
57515
  publication: 'not-applicable',
57124
57516
  };
@@ -57126,18 +57518,30 @@ class ObservePullRequestApprovalUseCase {
57126
57518
  if (initial.repositoryId !== target.repositoryId || initial.pullNumber !== target.pullNumber) {
57127
57519
  return { decision: { status: 'blocked', code: 'target-mismatch', detail: 'The resolved PR does not match the bound repository and number.' }, publication: 'not-applicable' };
57128
57520
  }
57129
- let decision = (0, pull_request_approval_1.decidePullRequestApproval)(policy, initial);
57521
+ let failure = initial.diagnostics?.[0] ? (0, approval_evidence_error_1.approvalDiagnosticError)(initial.diagnostics[0]) : undefined;
57522
+ let decision = failure
57523
+ ? { status: 'blocked', code: 'evidence-unavailable', detail: 'Approval evidence is unavailable; inspect the causal diagnostic in the observer Job Summary.' }
57524
+ : (0, pull_request_approval_1.decidePullRequestApproval)(policy, initial);
57130
57525
  let reviewId;
57131
57526
  if (decision.status === 'eligible') {
57132
57527
  let current;
57133
57528
  let currentPolicy;
57529
+ let readOperation = 'evidence';
57134
57530
  try {
57135
57531
  current = await this.port.loadEvidence(target);
57532
+ readOperation = 'policy';
57136
57533
  currentPolicy = await this.port.readPolicy(target);
57137
57534
  }
57138
- catch {
57535
+ catch (cause) {
57536
+ failure = evidenceFailure(cause, readOperation);
57537
+ current = undefined;
57139
57538
  decision = { status: 'blocked', code: 'pre-submit-unavailable', detail: 'Current approval evidence could not be reread before submission.' };
57140
57539
  }
57540
+ if (current?.diagnostics?.length) {
57541
+ failure = (0, approval_evidence_error_1.approvalDiagnosticError)(current.diagnostics[0]);
57542
+ current = undefined;
57543
+ decision = { status: 'blocked', code: 'pre-submit-unavailable', detail: 'Current evidence is unavailable; inspect the observer diagnostic.' };
57544
+ }
57141
57545
  if (current && currentPolicy !== rawPolicy) {
57142
57546
  decision = { status: 'pending', code: 'superseded', detail: 'The approval policy changed before submission; recheck the current head.' };
57143
57547
  }
@@ -57159,7 +57563,11 @@ class ObservePullRequestApprovalUseCase {
57159
57563
  const botReviews = readback.reviews.filter(review => review.userId === current.botUserId)
57160
57564
  .sort((left, right) => right.submittedAt.localeCompare(left.submittedAt) || right.id - left.id);
57161
57565
  const observed = botReviews.find(review => review.state === 'APPROVED' && review.commitId === current.headSha);
57162
- if (observed && observed.userId === current.botUserId
57566
+ if (readback.diagnostics?.length) {
57567
+ failure = (0, approval_evidence_error_1.approvalDiagnosticError)(readback.diagnostics[0]);
57568
+ decision = { status: 'pending', code: 'publication-unknown', detail: 'GitHub may have accepted the review; its final evidence is unavailable. Inspect the observer diagnostic before rechecking.' };
57569
+ }
57570
+ else if (observed && observed.userId === current.botUserId
57163
57571
  && observed.state === 'APPROVED' && observed.commitId === current.headSha
57164
57572
  && !botReviews.some(review => review.state === 'DISMISSED' && review.commitId === current.headSha)
57165
57573
  && readback.headSha === current.headSha && readback.baseSha === current.baseSha) {
@@ -57170,7 +57578,8 @@ class ObservePullRequestApprovalUseCase {
57170
57578
  decision = { status: 'pending', code: 'publication-unknown', detail: 'GitHub may have accepted the review; rerun to read it before any new submission.' };
57171
57579
  }
57172
57580
  }
57173
- catch {
57581
+ catch (cause) {
57582
+ failure = evidenceFailure(cause);
57174
57583
  decision = { status: 'pending', code: 'publication-unknown', detail: 'GitHub may have accepted the review; rerun to read it before any new submission.' };
57175
57584
  }
57176
57585
  }
@@ -57179,11 +57588,11 @@ class ObservePullRequestApprovalUseCase {
57179
57588
  try {
57180
57589
  // The adapter guards the current head again before editing the single card.
57181
57590
  await this.port.publishAssessment(target, initial, decision, reviewId);
57182
- return { decision, headSha: initial.headSha, evidence: initial, mode: policy.mode,
57591
+ return { decision, ...(failure ? { failure } : {}), headSha: initial.headSha, evidence: initial, mode: policy.mode,
57183
57592
  ...(reviewId ? { reviewId } : {}), publication: 'published' };
57184
57593
  }
57185
57594
  catch {
57186
- return { decision, headSha: initial.headSha, evidence: initial, mode: policy.mode,
57595
+ return { decision, ...(failure ? { failure } : {}), headSha: initial.headSha, evidence: initial, mode: policy.mode,
57187
57596
  ...(reviewId ? { reviewId } : {}), publication: 'failed' };
57188
57597
  }
57189
57598
  }
@@ -57199,6 +57608,10 @@ function sameRevisionAndEvidence(left, right) {
57199
57608
  function approvalReviewBody(headSha) {
57200
57609
  return `<!-- copilot:guarded-approval:v1 head="${headSha}" -->\nCopilot approved this revision (${headSha.slice(0, 7)}) after its configured CI and coverage gates passed and Bugbot reported no blocking findings. GitHub still applies branch rules. Configure a separate human-review requirement if needed; a bot approval may count toward a generic approval minimum.`;
57201
57610
  }
57611
+ function evidenceFailure(cause, operation = 'evidence') {
57612
+ return cause instanceof application_error_1.ApplicationError && cause.recovery?.id === 'approval-evidence-read-failed'
57613
+ ? cause : (0, approval_evidence_error_1.approvalEvidenceError)(operation, 'transport-unavailable');
57614
+ }
57202
57615
 
57203
57616
 
57204
57617
  /***/ }),
@@ -60806,7 +61219,7 @@ async function runVerification(context, gitCommitPort) {
60806
61219
  if (verifyCommands.length === 0)
60807
61220
  return undefined;
60808
61221
  (0, logging_ports_1.logInfo)(`Running ${verifyCommands.length} verify ${verifyCommands.length === 1 ? 'command' : 'commands'}...`);
60809
- const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true }));
61222
+ const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
60810
61223
  return verify.success
60811
61224
  ? undefined
60812
61225
  : verify.error ?? `Verify command failed: ${verify.failedCommand ?? "unknown"}.`;
@@ -63029,6 +63442,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
63029
63442
  exports.runVerifyCommands = runVerifyCommands;
63030
63443
  const logging_ports_1 = __nccwpck_require__(6152);
63031
63444
  const verify_command_policy_1 = __nccwpck_require__(96031);
63445
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
63032
63446
  async function runVerifyCommands(commands, execute) {
63033
63447
  for (const command of commands) {
63034
63448
  const result = await executeVerifyCommand(command, execute);
@@ -63047,7 +63461,11 @@ async function executeVerifyCommand(command, execute) {
63047
63461
  ? { success: true }
63048
63462
  : { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
63049
63463
  }
63050
- catch {
63464
+ catch (error) {
63465
+ if (error instanceof verification_runtime_policy_1.VerificationPrerequisiteError) {
63466
+ return { success: false, failedCommand: formatCommandForDiagnostics(parsed),
63467
+ error: `${error.message} Verification command: ${formatCommandForDiagnostics(parsed)}.` };
63468
+ }
63051
63469
  (0, logging_ports_1.logError)('Verify command failed.');
63052
63470
  return { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
63053
63471
  }
@@ -65764,6 +66182,7 @@ exports.titleUpdateFailure = titleUpdateFailure;
65764
66182
  const result_1 = __nccwpck_require__(73817);
65765
66183
  const application_error_1 = __nccwpck_require__(75999);
65766
66184
  const positive_integer_policy_1 = __nccwpck_require__(19879);
66185
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
65767
66186
  function projectUpdateTitleContext(source) {
65768
66187
  if (source.isIssue) {
65769
66188
  return Object.freeze({
@@ -65814,19 +66233,27 @@ async function runPullRequestTitleUpdate(param, taskId, issueRepository) {
65814
66233
  if (!linkedIssueNumber || linkedIssueNumber === param.pullRequestNumber) {
65815
66234
  return [skippedResult(taskId)];
65816
66235
  }
66236
+ const currentTitle = await issueRepository.getTitle(param.pullRequestNumber);
66237
+ if (currentTitle === undefined) {
66238
+ return [new result_1.Result({ id: taskId, success: false, executed: true,
66239
+ steps: ['The current pull request title could not be read. No title change was attempted.'],
66240
+ errors: [new application_error_1.ApplicationError('provider.unavailable', 'Unable to read the current pull request title.')] })];
66241
+ }
66242
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(currentTitle))
66243
+ return [skippedResult(taskId)];
65817
66244
  const issueTitle = await issueRepository.getTitle(linkedIssueNumber);
65818
66245
  if (issueTitle === undefined) {
65819
66246
  return [new result_1.Result({ id: taskId, success: false, executed: true, steps: ['Tried to update title, but there was a problem.'] })];
65820
66247
  }
65821
66248
  const title = await issueRepository.updatePullRequestTitle({
65822
- pullRequestTitle: param.pullRequestTitle,
66249
+ pullRequestTitle: currentTitle,
65823
66250
  issueTitle,
65824
66251
  issueNumber: linkedIssueNumber,
65825
66252
  pullRequestNumber: param.pullRequestNumber,
65826
66253
  labelFacts: param.labelFacts,
65827
66254
  });
65828
66255
  return title
65829
- ? [updatedResult(taskId, `The pull request's title was updated from \`${param.pullRequestTitle}\` to \`${title}\`.`)]
66256
+ ? [updatedResult(taskId, `The pull request's title was updated from \`${currentTitle}\` to \`${title}\`.`)]
65830
66257
  : [skippedResult(taskId)];
65831
66258
  }
65832
66259
  function titleUpdateFailure(taskId, error) {
@@ -66269,6 +66696,8 @@ exports.CheckPriorityIssueSizeUseCase = CheckPriorityIssueSizeUseCase;
66269
66696
 
66270
66697
  Object.defineProperty(exports, "__esModule", ({ value: true }));
66271
66698
  exports.CloseIssueAfterMergingUseCase = void 0;
66699
+ const reconcile_issue_completion_metadata_1 = __nccwpck_require__(70614);
66700
+ const closed_issue_reconciliation_error_1 = __nccwpck_require__(12183);
66272
66701
  const result_1 = __nccwpck_require__(73817);
66273
66702
  const issue_completion_1 = __nccwpck_require__(31147);
66274
66703
  const application_error_1 = __nccwpck_require__(75999);
@@ -66287,7 +66716,7 @@ class CloseIssueAfterMergingUseCase {
66287
66716
  steps: ['No separate safe linked issue and pull request were found; issue closure was skipped.'] })];
66288
66717
  let closedThisRun = false;
66289
66718
  let nativeClosed = false;
66290
- let labelsChanged = 0;
66719
+ const progress = (0, reconcile_issue_completion_metadata_1.completionRepairProgress)();
66291
66720
  try {
66292
66721
  const pull = await this.issues.readPullRequest(pullNumber);
66293
66722
  if (pull.number !== pullNumber || pull.state !== 'closed' || pull.merged !== true)
@@ -66311,44 +66740,21 @@ class CloseIssueAfterMergingUseCase {
66311
66740
  nativeClosed = facts.state === 'closed';
66312
66741
  if (!nativeClosed || closedThisRun && facts.reason !== 'completed')
66313
66742
  throw stale();
66314
- const fence = async () => {
66315
- const freshFacts = await read();
66316
- const freshPlan = (0, issue_completion_1.planIssueCompletion)(freshFacts, param.completionLabels);
66317
- if (freshPlan.kind !== 'closed' || freshFacts.reason !== facts.reason)
66318
- throw stale();
66319
- return freshPlan;
66320
- };
66321
- const plan = (0, issue_completion_1.planIssueCompletion)(facts, param.completionLabels);
66322
- if (plan.kind !== 'closed')
66323
- throw stale();
66324
- for (const label of plan.remove) {
66325
- const fresh = await fence();
66326
- if (fresh.remove.includes(label)) {
66327
- await target.removeLabel(label);
66328
- labelsChanged++;
66329
- }
66330
- }
66331
- for (const label of plan.add) {
66332
- const fresh = await fence();
66333
- if (fresh.add.includes(label)) {
66334
- await target.addLabel(label);
66335
- labelsChanged++;
66336
- }
66337
- }
66338
- const final = await fence();
66339
- if (final.remove.length || final.add.length)
66340
- throw stale();
66341
- return [new result_1.Result({ id: this.taskId, success: true, executed: closedThisRun || labelsChanged > 0,
66743
+ const repaired = await (0, reconcile_issue_completion_metadata_1.reconcileIssueCompletionMetadata)(target, number, param.completionLabels, progress, facts);
66744
+ nativeClosed = progress.nativeClosed;
66745
+ return [new result_1.Result({ id: this.taskId, success: true, executed: closedThisRun || progress.labelsChanged > 0,
66342
66746
  steps: [`Issue #${number} is closed and its completion metadata was verified after PR #${pullNumber} merged.`],
66343
- payload: { issueCompletion: Object.freeze({ number, nativeClosed, closedThisRun, labelsChanged, reason: facts.reason, reconciled: true }) } })];
66747
+ payload: { issueCompletion: Object.freeze({ number, nativeClosed, closedThisRun, labelsChanged: progress.labelsChanged, ...repaired, reconciled: true }) } })];
66344
66748
  }
66345
66749
  catch (error) {
66346
- const semanticError = (0, application_error_1.toApplicationError)(error, 'provider.unavailable', nativeClosed
66347
- ? 'The issue is closed, but completion metadata could not be fully verified. Retry the verified merged-PR operation.'
66348
- : 'Native issue completion could not be verified. Inspect the linked run before retrying.');
66349
- return [new result_1.Result({ id: this.taskId, success: false, executed: closedThisRun || labelsChanged > 0,
66750
+ if (progress.phase !== 'identity')
66751
+ nativeClosed = progress.nativeClosed;
66752
+ const semanticError = (0, closed_issue_reconciliation_error_1.closedIssueReconciliationError)(error, { resultId: this.taskId,
66753
+ phase: progress.phase, state: progress.state, reason: progress.reason,
66754
+ changed: progress.labelsChanged, remaining: progress.remaining });
66755
+ return [new result_1.Result({ id: this.taskId, success: false, executed: closedThisRun || progress.labelsChanged > 0,
66350
66756
  steps: [nativeClosed ? 'The native issue closure was retained; completion metadata remains unverified.' : 'Native issue completion remains unverified.'],
66351
- errors: [semanticError], payload: { issueCompletion: Object.freeze({ number, nativeClosed, closedThisRun, labelsChanged, reconciled: false }) } })];
66757
+ errors: [semanticError], payload: { issueCompletion: Object.freeze({ number, nativeClosed, closedThisRun, labelsChanged: progress.labelsChanged, reconciled: false }) } })];
66352
66758
  }
66353
66759
  }
66354
66760
  }
@@ -68363,6 +68769,8 @@ var _ApplicationError_cause;
68363
68769
  Object.defineProperty(exports, "__esModule", ({ value: true }));
68364
68770
  exports.ApplicationError = exports.APPLICATION_ERROR_METADATA = exports.APPLICATION_ERROR_RECOVERY_IDS = void 0;
68365
68771
  exports.isApplicationErrorCorrelationId = isApplicationErrorCorrelationId;
68772
+ const closed_issue_reconciliation_1 = __nccwpck_require__(21565);
68773
+ const approval_evidence_diagnostic_1 = __nccwpck_require__(98205);
68366
68774
  const branch_sync_validation_1 = __nccwpck_require__(90981);
68367
68775
  exports.APPLICATION_ERROR_RECOVERY_IDS = Object.freeze([
68368
68776
  'pull-request-link-restored',
@@ -68378,6 +68786,8 @@ exports.APPLICATION_ERROR_RECOVERY_IDS = Object.freeze([
68378
68786
  'sdd-draft-size-exceeded',
68379
68787
  'sdd-draft-format-invalid',
68380
68788
  'workspace-changes-rejected',
68789
+ 'closed-issue-reconciliation-failed',
68790
+ 'approval-evidence-read-failed',
68381
68791
  ]);
68382
68792
  const PRESERVED_STATE = 'Existing persisted state and completed external effects were preserved.';
68383
68793
  const UNCHANGED_STATE = 'No new state or external effect was created.';
@@ -68569,6 +68979,8 @@ class ApplicationError extends Error {
68569
68979
  exports.ApplicationError = ApplicationError;
68570
68980
  _ApplicationError_cause = new WeakMap();
68571
68981
  const RECOVERY_VARIABLE_KEYS = Object.freeze({
68982
+ 'closed-issue-reconciliation-failed': Object.freeze(['resultId', 'phase', 'state', 'reason', 'changed', 'remaining']),
68983
+ 'approval-evidence-read-failed': Object.freeze(['operation', 'reason', 'permission']),
68572
68984
  'pull-request-link-restored': Object.freeze([]),
68573
68985
  'pull-request-link-base-retained': Object.freeze([]),
68574
68986
  'pull-request-link-reference-retained': Object.freeze([]),
@@ -68621,6 +69033,20 @@ function normalizeApplicationErrorRecovery(recovery) {
68621
69033
  && !branch_sync_validation_1.BRANCH_SYNC_VALIDATION_CODES.some(code => code === variables.validationCode)) {
68622
69034
  throw new TypeError('Application error recovery synchronization validation code is invalid.');
68623
69035
  }
69036
+ if (recovery.id === 'closed-issue-reconciliation-failed'
69037
+ && (!closed_issue_reconciliation_1.CLOSED_ISSUE_RESULTS.some(value => value === variables.resultId)
69038
+ || !closed_issue_reconciliation_1.CLOSED_ISSUE_PHASES.some(value => value === variables.phase)
69039
+ || !['open', 'closed', 'unavailable'].includes(variables.state)
69040
+ || !closed_issue_reconciliation_1.CLOSED_ISSUE_REASONS.some(value => value === variables.reason)
69041
+ || ![variables.changed, variables.remaining].every(value => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 3000))) {
69042
+ throw new TypeError('Closed issue reconciliation diagnostic is invalid.');
69043
+ }
69044
+ if (recovery.id === 'approval-evidence-read-failed'
69045
+ && (!Object.prototype.hasOwnProperty.call(approval_evidence_diagnostic_1.APPROVAL_EVIDENCE_PERMISSIONS, variables.operation)
69046
+ || !approval_evidence_diagnostic_1.APPROVAL_EVIDENCE_REASONS.some(reason => reason === variables.reason)
69047
+ || approval_evidence_diagnostic_1.APPROVAL_EVIDENCE_PERMISSIONS[variables.operation] !== variables.permission)) {
69048
+ throw new TypeError('Approval evidence diagnostic is invalid.');
69049
+ }
68624
69050
  return Object.freeze({
68625
69051
  id: recovery.id,
68626
69052
  variables: Object.freeze({ ...variables }),
@@ -75228,6 +75654,7 @@ exports.IssueProgressTrackingRepository = IssueProgressTrackingRepository;
75228
75654
  Object.defineProperty(exports, "__esModule", ({ value: true }));
75229
75655
  exports.IssueTitleRepository = void 0;
75230
75656
  const issue_emoji_policy_1 = __nccwpck_require__(81201);
75657
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
75231
75658
  const issue_title_policy_1 = __nccwpck_require__(83179);
75232
75659
  const issue_title_update_1 = __nccwpck_require__(9229);
75233
75660
  class IssueTitleRepository {
@@ -75245,10 +75672,12 @@ class IssueTitleRepository {
75245
75672
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, issueTitle, formattedTitle, issueNumber, token);
75246
75673
  });
75247
75674
  };
75248
- this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, branchManagementEmoji, labels, token) => {
75675
+ this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, _branchManagementEmoji, labels, token) => {
75249
75676
  return (0, issue_title_update_1.withTitleUpdateLogging)(() => {
75250
- const emoji = (0, issue_emoji_policy_1.resolvePullRequestTitleEmoji)(labels, branchManagementEmoji);
75251
- const formattedTitle = `[#${issueNumber}] ${emoji} - ${(0, issue_title_policy_1.sanitizePullRequestTitle)((0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber))}`;
75677
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(pullRequestTitle))
75678
+ return Promise.resolve(undefined);
75679
+ const sourceTitle = (0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber);
75680
+ const formattedTitle = (0, pull_request_title_policy_1.generatedPullRequestTitle)(sourceTitle, (0, issue_title_policy_1.sanitizePullRequestTitle)(sourceTitle), issueNumber, labels);
75252
75681
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, pullRequestTitle, formattedTitle, pullRequestNumber, token);
75253
75682
  });
75254
75683
  };
@@ -76543,6 +76972,41 @@ function parseApprovalCoverageZip(value) {
76543
76972
  }
76544
76973
 
76545
76974
 
76975
+ /***/ }),
76976
+
76977
+ /***/ 9958:
76978
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
76979
+
76980
+ "use strict";
76981
+
76982
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
76983
+ exports.readApprovalEvidence = readApprovalEvidence;
76984
+ const application_error_1 = __nccwpck_require__(75999);
76985
+ const approval_evidence_error_1 = __nccwpck_require__(50519);
76986
+ const approval_evidence_diagnostic_1 = __nccwpck_require__(98205);
76987
+ /** Terminates provider exceptions; even unknown statuses never interpolate provider text. */
76988
+ async function readApprovalEvidence(operation, read) {
76989
+ try {
76990
+ return await read();
76991
+ }
76992
+ catch (cause) {
76993
+ if (cause instanceof application_error_1.ApplicationError && cause.recovery?.id === 'approval-evidence-read-failed')
76994
+ throw cause;
76995
+ const error = cause && typeof cause === 'object' ? cause : undefined;
76996
+ const response = error?.response;
76997
+ const status = error?.status;
76998
+ const rateLimited = status === 403 && (response?.headers?.['x-ratelimit-remaining'] === '0'
76999
+ || typeof response?.headers?.['retry-after'] === 'string' && /^\d{1,8}$/u.test(response.headers['retry-after']));
77000
+ const http = typeof status === 'number' ? `http-${status}` : undefined;
77001
+ const reason = rateLimited ? 'http-429'
77002
+ : approval_evidence_diagnostic_1.APPROVAL_EVIDENCE_REASONS.some(value => value === http) ? http
77003
+ : cause instanceof application_error_1.ApplicationError && cause.code === 'provider.contract-invalid' ? 'invalid-response'
77004
+ : status === undefined ? 'transport-unavailable' : 'invalid-response';
77005
+ throw (0, approval_evidence_error_1.approvalEvidenceError)(operation, reason);
77006
+ }
77007
+ }
77008
+
77009
+
76546
77010
  /***/ }),
76547
77011
 
76548
77012
  /***/ 55165:
@@ -76577,21 +77041,22 @@ exports.BugbotPullRequestRepository = BugbotPullRequestRepository;
76577
77041
  /***/ }),
76578
77042
 
76579
77043
  /***/ 68742:
76580
- /***/ ((__unused_webpack_module, exports) => {
77044
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
76581
77045
 
76582
77046
  "use strict";
76583
77047
 
76584
77048
  Object.defineProperty(exports, "__esModule", ({ value: true }));
76585
77049
  exports.readCurrentBaseRevision = readCurrentBaseRevision;
77050
+ const application_error_1 = __nccwpck_require__(75999);
76586
77051
  /** PR base metadata can lag a parent push; read the exact native branch ref. */
76587
77052
  async function readCurrentBaseRevision(port, target, baseRef) {
76588
77053
  if (typeof baseRef !== 'string' || baseRef.length === 0 || baseRef.length > 1024
76589
77054
  || baseRef.includes('\u0000') || /[\r\n]/u.test(baseRef))
76590
- throw new Error('The PR base ref is invalid.');
77055
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'The PR base ref is invalid.');
76591
77056
  const { data } = await port.getRef({ owner: target.owner, repo: target.repository, ref: `heads/${baseRef}` });
76592
77057
  if (data?.ref !== `refs/heads/${baseRef}` || data.object?.type !== 'commit' || typeof data.object.sha !== 'string'
76593
77058
  || !/^[a-f0-9]{40}$/u.test(data.object.sha))
76594
- throw new Error('The PR base ref cannot be verified.');
77059
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'The PR base ref cannot be verified.');
76595
77060
  return data.object.sha;
76596
77061
  }
76597
77062
 
@@ -76639,6 +77104,9 @@ var __importStar = (this && this.__importStar) || (function () {
76639
77104
  Object.defineProperty(exports, "__esModule", ({ value: true }));
76640
77105
  exports.PullRequestApprovalRepository = void 0;
76641
77106
  exports.readEffectiveApprovalPolicy = readEffectiveApprovalPolicy;
77107
+ const approval_evidence_read_1 = __nccwpck_require__(9958);
77108
+ const approval_evidence_error_1 = __nccwpck_require__(50519);
77109
+ const application_error_1 = __nccwpck_require__(75999);
76642
77110
  const current_base_revision_query_1 = __nccwpck_require__(68742);
76643
77111
  const logging_ports_1 = __nccwpck_require__(6152);
76644
77112
  const github = __importStar(__nccwpck_require__(78227));
@@ -76665,40 +77133,64 @@ class PullRequestApprovalRepository {
76665
77133
  }
76666
77134
  }
76667
77135
  async readPolicy(target) {
76668
- return (await this.readEffectivePolicy(target))?.value;
77136
+ return (0, approval_evidence_read_1.readApprovalEvidence)('policy', async () => (await this.readEffectivePolicy(target))?.value);
76669
77137
  }
76670
77138
  async readEffectivePolicy(target) {
76671
77139
  return readEffectiveApprovalPolicy(this.octokit, target);
76672
77140
  }
76673
77141
  async loadEvidence(target) {
76674
- const { data: pull } = await this.octokit.rest.pulls.get({
76675
- owner: target.owner, repo: target.repository, pull_number: target.pullNumber,
77142
+ const diagnostics = [];
77143
+ const { data: pull } = await (0, approval_evidence_read_1.readApprovalEvidence)('pull-request', async () => {
77144
+ const response = await this.octokit.rest.pulls.get({ owner: target.owner, repo: target.repository, pull_number: target.pullNumber });
77145
+ if (!response.data?.head || !response.data?.base || typeof response.data.head.sha !== 'string'
77146
+ || typeof response.data.head.ref !== 'string' || !Number.isSafeInteger(response.data.number)) {
77147
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('pull-request', 'invalid-response');
77148
+ }
77149
+ return response;
76676
77150
  });
76677
77151
  const headSha = pull.head.sha;
76678
77152
  const baseSha = await this.readCurrentBaseSha(target, pull.base.ref);
76679
- const policy = (0, pull_request_approval_policy_1.parsePullRequestApprovalPolicy)(await this.readPolicy(target));
77153
+ const policy = await (0, approval_evidence_read_1.readApprovalEvidence)('policy', async () => {
77154
+ const raw = await this.readPolicy(target);
77155
+ try {
77156
+ return (0, pull_request_approval_policy_1.parsePullRequestApprovalPolicy)(raw);
77157
+ }
77158
+ catch {
77159
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('policy', 'invalid-response');
77160
+ }
77161
+ });
76680
77162
  let testedMergeSha;
76681
77163
  if (pull.mergeable === true && /^[a-f0-9]{40}$/iu.test(pull.merge_commit_sha ?? '')) {
76682
77164
  try {
76683
- const merge = await this.octokit.rest.git.getCommit({
76684
- owner: target.owner, repo: target.repository, commit_sha: pull.merge_commit_sha,
77165
+ const merge = await (0, approval_evidence_read_1.readApprovalEvidence)('merge-commit', async () => {
77166
+ const response = await this.octokit.rest.git.getCommit({ owner: target.owner, repo: target.repository, commit_sha: pull.merge_commit_sha });
77167
+ if (!Array.isArray(response.data?.parents))
77168
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('merge-commit', 'invalid-response');
77169
+ return response;
76685
77170
  });
76686
77171
  if (merge.data.parents[0]?.sha === baseSha && merge.data.parents[1]?.sha === headSha
76687
77172
  && merge.data.parents.length === 2)
76688
77173
  testedMergeSha = pull.merge_commit_sha;
76689
77174
  }
76690
- catch { /* Missing or unreadable merge parentage is non-authorizing. */ }
77175
+ catch (cause) {
77176
+ collectDiagnostic(diagnostics, cause);
77177
+ }
76691
77178
  }
76692
77179
  const [files, reviews, comments, headChecks, mergeChecks, headRuns, mergeRuns, rules, user] = await Promise.all([
76693
- this.allPages(this.octokit.rest.pulls.listFiles, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
76694
- this.allPages(this.octokit.rest.pulls.listReviews, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
76695
- this.allPages(this.octokit.rest.issues.listComments, { owner: target.owner, repo: target.repository, issue_number: target.pullNumber }),
76696
- this.allPages(this.octokit.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: headSha, filter: 'all' }),
76697
- testedMergeSha ? this.allPages(this.octokit.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: testedMergeSha, filter: 'all' }) : Promise.resolve([]),
76698
- this.allPages(this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: headSha }),
76699
- testedMergeSha ? this.allPages(this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: testedMergeSha }) : Promise.resolve([]),
76700
- this.effectiveRules(target.owner, target.repository, pull.base.ref),
76701
- this.octokit.rest.users.getAuthenticated(),
77180
+ this.allPages('files', this.octokit.rest.pulls.listFiles, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
77181
+ this.allPages('reviews', this.octokit.rest.pulls.listReviews, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
77182
+ this.allPages('comments', this.octokit.rest.issues.listComments, { owner: target.owner, repo: target.repository, issue_number: target.pullNumber }),
77183
+ this.allPages('head-checks', this.octokit.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: headSha, filter: 'all' }),
77184
+ testedMergeSha ? this.allPages('merge-checks', this.octokit.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: testedMergeSha, filter: 'all' }) : Promise.resolve([]),
77185
+ this.allPages('head-runs', this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: headSha }),
77186
+ testedMergeSha ? this.allPages('merge-runs', this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: testedMergeSha }) : Promise.resolve([]),
77187
+ this.effectiveRules(target.owner, target.repository, pull.base.ref, diagnostics),
77188
+ (0, approval_evidence_read_1.readApprovalEvidence)('authenticated-user', async () => {
77189
+ const response = await this.octokit.rest.users.getAuthenticated();
77190
+ if (!Number.isSafeInteger(response.data?.id) || response.data.id < 1)
77191
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('authenticated-user', 'invalid-response');
77192
+ return response;
77193
+ }),
76702
77194
  ]);
76703
77195
  const branch = Object.entries(this.settings.branchPrefixes)
76704
77196
  .find(([, prefix]) => pull.head.ref.startsWith(`${prefix}/`));
@@ -76719,7 +77211,7 @@ class PullRequestApprovalRepository {
76719
77211
  });
76720
77212
  const currentJobs = await Promise.all(latestRuns.map(async (run) => ({
76721
77213
  run,
76722
- jobs: await this.allPages(this.octokit.rest.actions.listJobsForWorkflowRunAttempt, {
77214
+ jobs: await this.allPages('jobs', this.octokit.rest.actions.listJobsForWorkflowRunAttempt, {
76723
77215
  owner: target.owner, repo: target.repository, run_id: run.id, attempt_number: run.run_attempt,
76724
77216
  }),
76725
77217
  })));
@@ -76750,9 +77242,10 @@ class PullRequestApprovalRepository {
76750
77242
  submittedAt: review.submitted_at ?? '',
76751
77243
  }));
76752
77244
  const numericCoverage = policy.coverage.mode === 'numeric'
76753
- ? await this.numericCoverage(target, policy.coverage.artifactWorkflowName, headSha, baseSha, testedMergeSha, workflowRuns)
77245
+ ? await this.numericCoverage(target, policy.coverage.artifactWorkflowName, headSha, baseSha, testedMergeSha, workflowRuns, diagnostics)
76754
77246
  : undefined;
76755
77247
  return {
77248
+ ...(diagnostics.length ? { diagnostics: Object.freeze(diagnostics) } : {}),
76756
77249
  repositoryId: pull.base.repo?.id ?? 0,
76757
77250
  pullNumber: pull.number,
76758
77251
  headSha,
@@ -76786,7 +77279,7 @@ class PullRequestApprovalRepository {
76786
77279
  ...(numericCoverage ? { numericCoverage } : {}),
76787
77280
  };
76788
77281
  }
76789
- async numericCoverage(target, workflowName, headSha, baseSha, testedMergeSha, workflowRuns) {
77282
+ async numericCoverage(target, workflowName, headSha, baseSha, testedMergeSha, workflowRuns, diagnostics) {
76790
77283
  const candidates = workflowRuns.filter(run => run.name === workflowName
76791
77284
  && (run.head_sha === headSha || run.head_sha === testedMergeSha));
76792
77285
  const mergeCandidates = candidates.filter(run => run.head_sha === testedMergeSha);
@@ -76795,25 +77288,27 @@ class PullRequestApprovalRepository {
76795
77288
  if (!run || run.conclusion !== 'success' || run.status !== 'completed')
76796
77289
  return undefined;
76797
77290
  try {
76798
- const artifacts = await this.allPages(this.octokit.rest.actions.listWorkflowRunArtifacts, {
77291
+ const artifacts = await this.allPages('coverage-artifacts', this.octokit.rest.actions.listWorkflowRunArtifacts, {
76799
77292
  owner: target.owner, repo: target.repository, run_id: run.id,
76800
77293
  });
76801
77294
  const matches = artifacts.filter(artifact => artifact.name === 'copilot-diff-coverage-v1' && !artifact.expired);
76802
77295
  if (matches.length !== 1 || matches[0].size_in_bytes > 64 * 1024)
76803
- return undefined;
76804
- const response = await this.octokit.rest.actions.downloadArtifact({
77296
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('coverage-artifacts', 'artifact-unavailable');
77297
+ const response = await (0, approval_evidence_read_1.readApprovalEvidence)('coverage-download', async () => this.octokit.rest.actions.downloadArtifact({
76805
77298
  owner: target.owner, repo: target.repository, artifact_id: matches[0].id, archive_format: 'zip',
76806
- });
77299
+ }));
76807
77300
  const data = response.data;
76808
77301
  const bytes = data instanceof ArrayBuffer ? new Uint8Array(data)
76809
77302
  : data instanceof Uint8Array ? data
76810
77303
  : typeof data === 'string' ? Buffer.from(data, 'binary') : undefined;
76811
77304
  const attestation = bytes ? (0, approval_coverage_artifact_1.parseApprovalCoverageZip)(bytes) : undefined;
76812
- if (!attestation || attestation.repositoryId !== target.repositoryId
77305
+ if (!attestation)
77306
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('coverage-parse', 'artifact-invalid');
77307
+ if (attestation.repositoryId !== target.repositoryId
76813
77308
  || attestation.pullNumber !== target.pullNumber || attestation.headSha !== headSha
76814
77309
  || attestation.baseSha !== baseSha || attestation.workflowRunId !== run.id
76815
77310
  || attestation.workflowRunAttempt !== run.run_attempt)
76816
- return undefined;
77311
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('coverage-parse', 'artifact-mismatch');
76817
77312
  return {
76818
77313
  coveredChangedLines: attestation.coveredChangedLines,
76819
77314
  totalChangedLines: attestation.totalChangedLines,
@@ -76821,7 +77316,8 @@ class PullRequestApprovalRepository {
76821
77316
  baseSha,
76822
77317
  };
76823
77318
  }
76824
- catch {
77319
+ catch (cause) {
77320
+ collectDiagnostic(diagnostics, cause);
76825
77321
  return undefined;
76826
77322
  }
76827
77323
  }
@@ -76847,7 +77343,7 @@ class PullRequestApprovalRepository {
76847
77343
  throw new Error('PR head or base changed before assessment publication.');
76848
77344
  }
76849
77345
  const user = await this.octokit.rest.users.getAuthenticated();
76850
- const comments = await this.allPages(this.octokit.rest.issues.listComments, {
77346
+ const comments = await this.allPages('comments', this.octokit.rest.issues.listComments, {
76851
77347
  owner: target.owner, repo: target.repository, issue_number: target.pullNumber,
76852
77348
  });
76853
77349
  const card = [...comments].reverse().find(comment => comment.user?.id === user.data.id
@@ -76893,24 +77389,26 @@ class PullRequestApprovalRepository {
76893
77389
  }
76894
77390
  }
76895
77391
  async readCurrentBaseSha(target, baseRef) {
76896
- return (0, current_base_revision_query_1.readCurrentBaseRevision)(this.octokit.rest.git, target, baseRef);
77392
+ return (0, approval_evidence_read_1.readApprovalEvidence)('base-ref', () => (0, current_base_revision_query_1.readCurrentBaseRevision)(this.octokit.rest.git, target, baseRef));
76897
77393
  }
76898
- async effectiveRules(owner, repo, branch) {
77394
+ async effectiveRules(owner, repo, branch, diagnostics) {
76899
77395
  try {
76900
- const rulesResponse = await this.octokit.request('GET /repos/{owner}/{repo}/rules/branches/{branch}', { owner, repo, branch });
77396
+ const rulesResponse = await (0, approval_evidence_read_1.readApprovalEvidence)('rules', async () => this.octokit.request('GET /repos/{owner}/{repo}/rules/branches/{branch}', { owner, repo, branch }));
76901
77397
  if (!Array.isArray(rulesResponse.data) || rulesResponse.data.some((rule) => !record(rule)
76902
77398
  || typeof record(rule)?.type !== 'string' || record(rule)?.type === '')) {
76903
- throw new Error('GitHub returned an invalid effective rules inventory.');
77399
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('rules', 'invalid-response');
76904
77400
  }
76905
77401
  const rules = rulesResponse.data;
76906
77402
  let classic;
76907
77403
  try {
76908
77404
  const response = await this.octokit.rest.repos.getBranchProtection({ owner, repo, branch });
77405
+ if (!record(response.data))
77406
+ throw (0, approval_evidence_error_1.approvalEvidenceError)('classic-protection', 'invalid-response');
76909
77407
  classic = response.data;
76910
77408
  }
76911
77409
  catch (error) {
76912
77410
  if (statusOf(error) !== 404)
76913
- throw error;
77411
+ await (0, approval_evidence_read_1.readApprovalEvidence)('classic-protection', async () => { throw error; });
76914
77412
  }
76915
77413
  const reviewRules = rules.filter(rule => rule.type === 'pull_request');
76916
77414
  const classicReview = classic?.required_pull_request_reviews;
@@ -76936,23 +77434,26 @@ class PullRequestApprovalRepository {
76936
77434
  }
76937
77435
  return { readable: true, dismissesStaleReviews: hasStaleRule && allStale, requiredChecks: [...requiredChecks] };
76938
77436
  }
76939
- catch {
77437
+ catch (cause) {
77438
+ collectDiagnostic(diagnostics, cause);
76940
77439
  return { readable: false, dismissesStaleReviews: false, requiredChecks: [] };
76941
77440
  }
76942
77441
  }
76943
- async allPages(method, params) {
76944
- const result = [];
76945
- for await (const response of this.octokit.paginate.iterator(method, { ...params, per_page: 100 })) {
76946
- const page = Array.isArray(response.data) ? response.data
76947
- : record(response.data)?.check_runs ?? record(response.data)?.workflow_runs
76948
- ?? record(response.data)?.artifacts ?? record(response.data)?.jobs;
76949
- if (!Array.isArray(page))
76950
- throw new Error('GitHub pagination returned an invalid page.');
76951
- result.push(...page);
76952
- if (result.length > 3000)
76953
- throw new Error('Approval evidence pagination exceeded the safe bound.');
76954
- }
76955
- return result;
77442
+ async allPages(operation, method, params) {
77443
+ return (0, approval_evidence_read_1.readApprovalEvidence)(operation, async () => {
77444
+ const result = [];
77445
+ for await (const response of this.octokit.paginate.iterator(method, { ...params, per_page: 100 })) {
77446
+ const page = Array.isArray(response.data) ? response.data
77447
+ : record(response.data)?.check_runs ?? record(response.data)?.workflow_runs
77448
+ ?? record(response.data)?.artifacts ?? record(response.data)?.jobs;
77449
+ if (!Array.isArray(page))
77450
+ throw (0, approval_evidence_error_1.approvalEvidenceError)(operation, 'invalid-page');
77451
+ result.push(...page);
77452
+ if (result.length > 3000)
77453
+ throw (0, approval_evidence_error_1.approvalEvidenceError)(operation, 'page-limit');
77454
+ }
77455
+ return result;
77456
+ });
76956
77457
  }
76957
77458
  }
76958
77459
  exports.PullRequestApprovalRepository = PullRequestApprovalRepository;
@@ -76989,7 +77490,7 @@ function array(value) { return Array.isArray(value) ? value : []; }
76989
77490
  async function readEffectiveApprovalPolicy(octokit, target) {
76990
77491
  const admit = (source, value) => {
76991
77492
  if (typeof value !== 'string' || value.length > 65536)
76992
- throw new Error('Approval policy response is malformed or unbounded.');
77493
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'Approval policy response is malformed or unbounded.');
76993
77494
  return { source, value };
76994
77495
  };
76995
77496
  try {
@@ -77013,6 +77514,14 @@ async function readEffectiveApprovalPolicy(octokit, target) {
77013
77514
  throw error;
77014
77515
  }
77015
77516
  }
77517
+ function collectDiagnostic(diagnostics, cause) {
77518
+ if (cause instanceof application_error_1.ApplicationError && cause.recovery?.id === 'approval-evidence-read-failed') {
77519
+ diagnostics.push(cause.recovery.variables);
77520
+ }
77521
+ else {
77522
+ diagnostics.push((0, approval_evidence_error_1.approvalEvidenceError)('evidence', 'invalid-response').recovery.variables);
77523
+ }
77524
+ }
77016
77525
 
77017
77526
 
77018
77527
  /***/ }),
@@ -79253,6 +79762,44 @@ class AgentResponseLengthFailure extends Error {
79253
79762
  exports.AgentResponseLengthFailure = AgentResponseLengthFailure;
79254
79763
 
79255
79764
 
79765
+ /***/ }),
79766
+
79767
+ /***/ 98205:
79768
+ /***/ ((__unused_webpack_module, exports) => {
79769
+
79770
+ "use strict";
79771
+
79772
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
79773
+ exports.APPROVAL_EVIDENCE_REASONS = exports.APPROVAL_EVIDENCE_PERMISSIONS = void 0;
79774
+ /** Closed vocabulary: no provider text, URLs, headers, policy values or credentials. */
79775
+ exports.APPROVAL_EVIDENCE_PERMISSIONS = Object.freeze({
79776
+ 'evidence': 'repository-read',
79777
+ 'pull-request': 'pull-requests-read',
79778
+ 'base-ref': 'contents-read',
79779
+ 'merge-commit': 'contents-read',
79780
+ 'policy': 'actions-variables-read',
79781
+ 'files': 'pull-requests-read',
79782
+ 'reviews': 'pull-requests-read',
79783
+ 'comments': 'issues-read',
79784
+ 'head-checks': 'checks-read',
79785
+ 'merge-checks': 'checks-read',
79786
+ 'head-runs': 'actions-read',
79787
+ 'merge-runs': 'actions-read',
79788
+ 'jobs': 'actions-read',
79789
+ 'rules': 'metadata-read',
79790
+ 'classic-protection': 'administration-read',
79791
+ 'authenticated-user': 'authenticated-user-read',
79792
+ 'coverage-artifacts': 'actions-read',
79793
+ 'coverage-download': 'actions-read',
79794
+ 'coverage-parse': 'actions-read',
79795
+ });
79796
+ exports.APPROVAL_EVIDENCE_REASONS = Object.freeze([
79797
+ 'http-400', 'http-401', 'http-403', 'http-404', 'http-409', 'http-422', 'http-429',
79798
+ 'http-500', 'http-502', 'http-503', 'http-504', 'transport-unavailable',
79799
+ 'invalid-response', 'invalid-page', 'page-limit', 'artifact-unavailable', 'artifact-invalid', 'artifact-mismatch',
79800
+ ]);
79801
+
79802
+
79256
79803
  /***/ }),
79257
79804
 
79258
79805
  /***/ 51114:
@@ -79813,6 +80360,25 @@ function countActionableBugbotFindings(counts) {
79813
80360
  }
79814
80361
 
79815
80362
 
80363
+ /***/ }),
80364
+
80365
+ /***/ 21565:
80366
+ /***/ ((__unused_webpack_module, exports) => {
80367
+
80368
+ "use strict";
80369
+
80370
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
80371
+ exports.CLOSED_ISSUE_REASONS = exports.CLOSED_ISSUE_PHASES = exports.CLOSED_ISSUE_RESULTS = void 0;
80372
+ exports.CLOSED_ISSUE_RESULTS = Object.freeze([
80373
+ 'ReconcileClosedIssueMetadataUseCase', 'CloseIssueAfterMergingUseCase', 'RetireBranchSyncUseCase', 'RetireProgressUseCase',
80374
+ ]);
80375
+ exports.CLOSED_ISSUE_PHASES = Object.freeze([
80376
+ 'identity', 'read', 'native-fence', 'label-remove', 'label-add', 'metadata-verification',
80377
+ 'card-inventory', 'card-freshness', 'card-update', 'card-verification',
80378
+ ]);
80379
+ exports.CLOSED_ISSUE_REASONS = Object.freeze(['completed', 'not_planned', 'duplicate', 'reopened', 'unknown', 'unavailable']);
80380
+
80381
+
79816
80382
  /***/ }),
79817
80383
 
79818
80384
  /***/ 77454:
@@ -86711,6 +87277,7 @@ const exec = __importStar(__nccwpck_require__(18538));
86711
87277
  const git_authentication_environment_1 = __nccwpck_require__(16535);
86712
87278
  const untrusted_command_environment_1 = __nccwpck_require__(2304);
86713
87279
  const git_hook_isolation_1 = __nccwpck_require__(39764);
87280
+ const verification_runtime_preflight_1 = __nccwpck_require__(23100);
86714
87281
  class GitCommitAdapter {
86715
87282
  constructor(executeCommand = (program, args, options) => options
86716
87283
  ? exec.exec(program, args, {
@@ -86720,16 +87287,21 @@ class GitCommitAdapter {
86720
87287
  ...(options.stdout ? { listeners: { stdout: options.stdout } } : {}),
86721
87288
  ...(options.env ? { env: options.env } : {}),
86722
87289
  })
86723
- : exec.exec(program, args)) {
87290
+ : exec.exec(program, args), checkPrerequisites = verification_runtime_preflight_1.assertVerificationRuntimePrerequisites) {
86724
87291
  this.executeCommand = executeCommand;
87292
+ this.checkPrerequisites = checkPrerequisites;
86725
87293
  }
86726
87294
  async execute(program, args, options) {
87295
+ if (options?.verifyRuntimePrerequisites && !options.untrusted)
87296
+ throw new Error('Runtime preflight requires credential-free verification.');
86727
87297
  if (!options?.untrusted)
86728
87298
  return options ? this.executeCommand(program, args, options) : this.executeCommand(program, args);
86729
87299
  if (options.env)
86730
87300
  throw new Error('Untrusted command execution does not accept a caller-supplied environment.');
86731
87301
  const runtime = (0, untrusted_command_environment_1.prepareUntrustedCommandEnvironment)();
86732
87302
  try {
87303
+ if (options.verifyRuntimePrerequisites)
87304
+ this.checkPrerequisites(runtime.environment);
86733
87305
  return await this.executeCommand(program, args, {
86734
87306
  ...(options.stdout ? { stdout: options.stdout } : {}),
86735
87307
  env: runtime.environment,
@@ -88044,6 +88616,7 @@ const node_path_1 = __nccwpck_require__(49411);
88044
88616
  const agent_private_install_root_1 = __nccwpck_require__(44640);
88045
88617
  const ALLOWED_VARIABLES = [
88046
88618
  'PATH',
88619
+ 'JAVA_HOME',
88047
88620
  'LANG',
88048
88621
  'LANGUAGE',
88049
88622
  'LC_ALL',
@@ -88103,6 +88676,132 @@ function prepareUntrustedCommandEnvironment(source = process.env, platform = pro
88103
88676
  }
88104
88677
 
88105
88678
 
88679
+ /***/ }),
88680
+
88681
+ /***/ 91053:
88682
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
88683
+
88684
+ "use strict";
88685
+
88686
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88687
+ exports.readVerificationRuntimeManifest = readVerificationRuntimeManifest;
88688
+ const node_fs_1 = __nccwpck_require__(87561);
88689
+ const node_path_1 = __nccwpck_require__(49411);
88690
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
88691
+ const MAX_MANIFEST_BYTES = 16 * 1024;
88692
+ function readVerificationRuntimeManifest(root) {
88693
+ const path = (0, node_path_1.resolve)(root, verification_runtime_policy_1.VERIFICATION_RUNTIME_MANIFEST);
88694
+ let descriptor;
88695
+ try {
88696
+ let directory;
88697
+ try {
88698
+ directory = (0, node_fs_1.lstatSync)((0, node_path_1.join)(root, '.copilot'));
88699
+ }
88700
+ catch (error) {
88701
+ if (error.code === 'ENOENT')
88702
+ return [];
88703
+ throw error;
88704
+ }
88705
+ if (!directory.isDirectory() || directory.isSymbolicLink()
88706
+ || (0, node_fs_1.realpathSync)((0, node_path_1.join)(root, '.copilot')) !== (0, node_path_1.join)((0, node_fs_1.realpathSync)(root), '.copilot'))
88707
+ throw new Error('Unsafe manifest parent');
88708
+ let entry;
88709
+ try {
88710
+ entry = (0, node_fs_1.lstatSync)(path, { bigint: true });
88711
+ }
88712
+ catch (error) {
88713
+ if (error.code === 'ENOENT')
88714
+ return [];
88715
+ throw error;
88716
+ }
88717
+ if (!entry.isFile() || entry.isSymbolicLink() || entry.nlink !== 1n || entry.size > BigInt(MAX_MANIFEST_BYTES))
88718
+ throw new Error('Unsafe manifest');
88719
+ descriptor = (0, node_fs_1.openSync)(path, node_fs_1.constants.O_RDONLY | (node_fs_1.constants.O_NOFOLLOW ?? 0));
88720
+ const opened = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
88721
+ if (!opened.isFile() || opened.nlink !== 1n || opened.dev !== entry.dev || opened.ino !== entry.ino
88722
+ || opened.size > BigInt(MAX_MANIFEST_BYTES))
88723
+ throw new Error('Manifest changed');
88724
+ const bytes = Buffer.alloc(MAX_MANIFEST_BYTES + 1);
88725
+ const size = (0, node_fs_1.readSync)(descriptor, bytes, 0, bytes.length, 0);
88726
+ if (size > MAX_MANIFEST_BYTES)
88727
+ throw new Error('Oversized manifest');
88728
+ return (0, verification_runtime_policy_1.parseVerificationRuntimeManifest)(JSON.parse(bytes.subarray(0, size).toString('utf8')));
88729
+ }
88730
+ catch {
88731
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('manifest-invalid');
88732
+ }
88733
+ finally {
88734
+ if (descriptor !== undefined)
88735
+ (0, node_fs_1.closeSync)(descriptor);
88736
+ }
88737
+ }
88738
+
88739
+
88740
+ /***/ }),
88741
+
88742
+ /***/ 23100:
88743
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
88744
+
88745
+ "use strict";
88746
+
88747
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88748
+ exports.assertVerificationRuntimePrerequisites = assertVerificationRuntimePrerequisites;
88749
+ const node_child_process_1 = __nccwpck_require__(17718);
88750
+ const node_path_1 = __nccwpck_require__(49411);
88751
+ const verification_runtime_manifest_1 = __nccwpck_require__(91053);
88752
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
88753
+ const probe = (program, args, environment) => {
88754
+ const result = (0, node_child_process_1.spawnSync)(program, [...args], { env: environment, encoding: 'utf8', shell: false,
88755
+ windowsHide: true, timeout: 5000, maxBuffer: 8192, stdio: ['ignore', 'pipe', 'pipe'] });
88756
+ return { status: result.status, output: `${result.stdout ?? ''}\n${result.stderr ?? ''}`, failed: !!result.error };
88757
+ };
88758
+ const hasControlCharacter = (value) => [...value].some(character => character.charCodeAt(0) < 32);
88759
+ /** Fixed version probes only; never installs a runtime or executes a repository-provided bootstrap. */
88760
+ function assertVerificationRuntimePrerequisites(environment, root = process.cwd(), run = probe, platform = process.platform, job = process.env.GITHUB_JOB) {
88761
+ for (const requirement of (0, verification_runtime_manifest_1.readVerificationRuntimeManifest)(root)) {
88762
+ checkRuntime(requirement, environment, run, platform, job);
88763
+ }
88764
+ }
88765
+ function checkRuntime(requirement, environment, run, platform, job) {
88766
+ const spec = verification_runtime_policy_1.VERIFICATION_RUNTIME_SPECS[requirement.runtime];
88767
+ let program = spec.program;
88768
+ let args = spec.args;
88769
+ if (requirement.runtime === 'java' && environment.JAVA_HOME) {
88770
+ const paths = platform === 'win32' ? node_path_1.win32 : node_path_1.posix;
88771
+ if (!paths.isAbsolute(environment.JAVA_HOME) || hasControlCharacter(environment.JAVA_HOME)) {
88772
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88773
+ }
88774
+ program = paths.join(environment.JAVA_HOME, 'bin', platform === 'win32' ? 'java.exe' : 'java');
88775
+ }
88776
+ else if (requirement.runtime === 'python' && platform === 'win32')
88777
+ program = 'python';
88778
+ else if (requirement.runtime === 'pnpm' && platform === 'win32') {
88779
+ const systemRoot = environment.SystemRoot;
88780
+ if (!systemRoot || !node_path_1.win32.isAbsolute(systemRoot) || hasControlCharacter(systemRoot)) {
88781
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88782
+ }
88783
+ program = node_path_1.win32.join(systemRoot, 'System32', 'cmd.exe');
88784
+ args = ['/d', '/s', '/c', 'pnpm --version'];
88785
+ }
88786
+ let result;
88787
+ try {
88788
+ result = run(program, args, environment);
88789
+ }
88790
+ catch {
88791
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88792
+ }
88793
+ if (result.failed || result.status !== 0 || result.output.length > 8192) {
88794
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88795
+ }
88796
+ const observed = (0, verification_runtime_policy_1.verificationRuntimeVersion)(requirement.runtime, result.output);
88797
+ if (!observed)
88798
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unreadable-version', requirement, undefined, job);
88799
+ if (!(0, verification_runtime_policy_1.verificationRuntimeMatches)(requirement.version, observed)) {
88800
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('version-mismatch', requirement, observed, job);
88801
+ }
88802
+ }
88803
+
88804
+
88106
88805
  /***/ }),
88107
88806
 
88108
88807
  /***/ 92540: