@vypdev/copilot 3.9.3 → 3.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36897,6 +36897,7 @@ var __importStar = (this && this.__importStar) || (function () {
36897
36897
  Object.defineProperty(exports, "__esModule", ({ value: true }));
36898
36898
  exports.runGitHubAction = runGitHubAction;
36899
36899
  exports.runGitHubActionEntry = runGitHubActionEntry;
36900
+ const native_verification_controller_1 = __nccwpck_require__(71046);
36900
36901
  const issue_completion_composition_root_1 = __nccwpck_require__(63719);
36901
36902
  const core = __importStar(__nccwpck_require__(75855));
36902
36903
  const github = __importStar(__nccwpck_require__(78227));
@@ -37081,7 +37082,16 @@ async function runGitHubActionEntry(run = runGitHubAction) {
37081
37082
  catch (cause) {
37082
37083
  const semanticError = (0, application_error_1.toApplicationError)(cause, 'workflow.failed', 'GitHub Action execution failed.');
37083
37084
  (0, logger_1.logError)(semanticError);
37084
- core.setFailed((0, application_error_presentation_policy_1.renderApplicationErrorText)(semanticError, earlyGithubActionErrorMessage()));
37085
+ const message = earlyGithubActionErrorMessage();
37086
+ core.setFailed((0, application_error_presentation_policy_1.renderApplicationErrorText)(semanticError, message));
37087
+ if (semanticError.recovery?.id.startsWith('stored-configuration-')) {
37088
+ try {
37089
+ await (0, github_action_summary_composition_root_1.createGithubActionSummaryCompositionRoot)().publish((0, application_error_presentation_policy_1.renderApplicationErrorMarkdown)(semanticError, message));
37090
+ }
37091
+ catch (summaryCause) {
37092
+ (0, logger_1.logError)((0, application_error_1.toApplicationError)(summaryCause, 'provider.unavailable', 'Unable to publish the configuration failure summary.'));
37093
+ }
37094
+ }
37085
37095
  }
37086
37096
  });
37087
37097
  }
@@ -37097,7 +37107,7 @@ function earlyGithubActionErrorMessage() {
37097
37107
  // Only auto-run when executed as the action entry (not when imported by tests)
37098
37108
  /* istanbul ignore next -- the bundled production entry is covered by the Action smoke path. */
37099
37109
  if (typeof process.env.JEST_WORKER_ID === 'undefined') {
37100
- void runGitHubActionEntry();
37110
+ void runGitHubActionEntry(() => (0, native_verification_controller_1.runNativeVerificationEntry)(runGitHubActionEntry));
37101
37111
  }
37102
37112
 
37103
37113
 
@@ -37522,6 +37532,7 @@ async function buildGithubActionExecution(input) {
37522
37532
  commitPrefixBuilder: getCommitPrefixBuilder(getInput),
37523
37533
  issue: (0, configuration_builders_1.buildIssue)((0, input_boolean_policy_1.parseIssueWorkflowBoolean)(getInput(input_keys_1.INPUT_KEYS.ISSUE_MANAGED_BRANCHES), input_keys_1.INPUT_KEYS.ISSUE_MANAGED_BRANCHES, true), (0, input_boolean_policy_1.isEnabledInput)(getInput(input_keys_1.INPUT_KEYS.REOPEN_ISSUE_ON_PUSH)), (0, input_number_policy_1.parseIntegerInput)(getInput(input_keys_1.INPUT_KEYS.DESIRED_ASSIGNEES_COUNT), 0), eventInputs),
37524
37534
  preBranchSdd: (0, input_boolean_policy_1.parseIssueWorkflowBoolean)(getInput(input_keys_1.INPUT_KEYS.PRE_BRANCH_SDD), input_keys_1.INPUT_KEYS.PRE_BRANCH_SDD, false),
37535
+ verificationSetup: (0, input_boolean_policy_1.parseIssueWorkflowBoolean)(getInput(input_keys_1.INPUT_KEYS.VERIFICATION_SETUP), input_keys_1.INPUT_KEYS.VERIFICATION_SETUP, false),
37525
37536
  pullRequest: (0, configuration_builders_1.buildPullRequest)((0, input_number_policy_1.parseIntegerInput)(getInput(input_keys_1.INPUT_KEYS.PULL_REQUEST_DESIRED_ASSIGNEES_COUNT), 0), (0, input_number_policy_1.parseIntegerInput)(getInput(input_keys_1.INPUT_KEYS.PULL_REQUEST_DESIRED_REVIEWERS_COUNT), 0), eventInputs),
37526
37537
  emoji: (0, configuration_builders_1.buildEmoji)(getInput(input_keys_1.INPUT_KEYS.EMOJI_LABELED_TITLE) === 'true', getInput(input_keys_1.INPUT_KEYS.BRANCH_MANAGEMENT_EMOJI)),
37527
37538
  tokens: (0, configuration_builders_1.buildTokens)(token),
@@ -38737,6 +38748,7 @@ exports.INPUT_KEYS = {
38737
38748
  // Issue
38738
38749
  ISSUE_MANAGED_BRANCHES: 'issue-managed-branches',
38739
38750
  PRE_BRANCH_SDD: 'pre-branch-sdd',
38751
+ VERIFICATION_SETUP: 'verification-setup',
38740
38752
  REOPEN_ISSUE_ON_PUSH: 'reopen-issue-on-push',
38741
38753
  DESIRED_ASSIGNEES_COUNT: 'desired-assignees-count',
38742
38754
  // Pull Request
@@ -38857,6 +38869,46 @@ function approvalDiagnosticError(diagnostic) {
38857
38869
  }
38858
38870
 
38859
38871
 
38872
+ /***/ }),
38873
+
38874
+ /***/ 82937:
38875
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
38876
+
38877
+ "use strict";
38878
+
38879
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
38880
+ exports.BugbotMutationError = void 0;
38881
+ exports.bugbotMutationError = bugbotMutationError;
38882
+ const application_error_1 = __nccwpck_require__(75999);
38883
+ const pull_request_review_errors_1 = __nccwpck_require__(46445);
38884
+ class BugbotMutationError extends application_error_1.ApplicationError {
38885
+ constructor(diagnostic) {
38886
+ super(diagnostic.errorCode, `Bugbot ${diagnostic.stage} failed: operation=${diagnostic.operation}; finding=${diagnostic.findingId}; affected=${diagnostic.affectedCount}; ${diagnostic.providerStatus}; provider-reference=${diagnostic.providerReference}. Completed effects are retained; correct the named cause and recheck the same target.`);
38887
+ this.diagnostic = diagnostic;
38888
+ }
38889
+ }
38890
+ exports.BugbotMutationError = BugbotMutationError;
38891
+ function bugbotMutationError(cause, stage, findingIds, fallback, affectedCount = findingIds.length) {
38892
+ if (cause instanceof BugbotMutationError)
38893
+ return cause;
38894
+ const provider = cause instanceof pull_request_review_errors_1.PullRequestReviewOperationError ? cause : undefined;
38895
+ const status = provider?.providerStatus;
38896
+ const errorCode = status === 401 ? 'authorization.credential-invalid' : status === 403 ? 'authorization.denied'
38897
+ : status === 404 ? 'provider.not-found' : status === 409 ? 'provider.conflict'
38898
+ : status === 429 ? 'provider.rate-limited'
38899
+ : status === 408 || status === 425 ? 'provider.unavailable'
38900
+ : status && status < 500 ? 'provider.contract-invalid' : 'provider.unavailable';
38901
+ const first = findingIds[0];
38902
+ return new BugbotMutationError(Object.freeze({
38903
+ stage, operation: provider?.operation ?? fallback,
38904
+ findingId: typeof first === 'string' && /^[A-Za-z0-9_./:-]{1,200}$/.test(first) ? first : 'unavailable',
38905
+ affectedCount: Math.min(affectedCount, 10000),
38906
+ providerStatus: status ? `http-${status}` : 'http-unavailable',
38907
+ providerReference: provider?.providerReference ?? 'unavailable', errorCode,
38908
+ }));
38909
+ }
38910
+
38911
+
38860
38912
  /***/ }),
38861
38913
 
38862
38914
  /***/ 12183:
@@ -40666,7 +40718,26 @@ const SPANISH_CONTENT = Object.freeze({
40666
40718
  retainedState: PRESERVED_STATE_ES,
40667
40719
  }),
40668
40720
  });
40721
+ const STORED_CONFIGURATION_ACTION_EN = 'A maintainer must review {recoveryGuide}. Preserve a copy before removing only a verified obsolete unmanaged block. If managed branch, release, hotfix or orchestration state may exist, stop and restore verified supported state with a maintainer. Do not just add a schema version or delete managed state. Correct the configuration before rerunning; retrying unchanged state will fail again.';
40722
+ const STORED_CONFIGURATION_ACTION_ES = 'Un mantenedor debe revisar {recoveryGuide}. Conserva una copia antes de retirar solo un bloque obsoleto confirmado como no gestionado. Si puede existir estado gestionado de ramas, releases, hotfixes u orquestación, detente y restaura estado compatible verificado con un mantenedor. No añadas simplemente una versión de esquema ni borres estado gestionado. Corrige la configuración antes de reejecutar; el mismo estado volverá a fallar.';
40723
+ const STORED_CONFIGURATION_RETAINED_EN = 'The issue/PR description and stored configuration were not changed by this read.';
40724
+ const STORED_CONFIGURATION_RETAINED_ES = 'Esta lectura no modificó la descripción de la issue/PR ni su configuración almacenada.';
40669
40725
  const ENGLISH_RECOVERY_CONTENT = Object.freeze({
40726
+ 'stored-configuration-schema-missing': Object.freeze({
40727
+ impact: 'Automation stopped for issue/PR #{issueNumber}: the stored configuration has no schema version; version {expectedVersion} is required.',
40728
+ action: STORED_CONFIGURATION_ACTION_EN,
40729
+ retainedState: STORED_CONFIGURATION_RETAINED_EN,
40730
+ }),
40731
+ 'stored-configuration-schema-unsupported': Object.freeze({
40732
+ impact: 'Automation stopped for issue/PR #{issueNumber}: stored schema version {actualVersion} is unsupported; version {expectedVersion} is required.',
40733
+ action: STORED_CONFIGURATION_ACTION_EN,
40734
+ retainedState: STORED_CONFIGURATION_RETAINED_EN,
40735
+ }),
40736
+ 'stored-configuration-invalid': Object.freeze({
40737
+ impact: 'Automation stopped for issue/PR #{issueNumber}: the stored configuration, markers or schema value are malformed; valid schema version {expectedVersion} is required.',
40738
+ action: STORED_CONFIGURATION_ACTION_EN,
40739
+ retainedState: STORED_CONFIGURATION_RETAINED_EN,
40740
+ }),
40670
40741
  'closed-issue-reconciliation-failed': Object.freeze({
40671
40742
  impact: 'Issue cleanup remains unverified: {resultId}, phase {phase}; native state {state}, reason {reason}.',
40672
40743
  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.',
@@ -40682,6 +40753,26 @@ const ENGLISH_RECOVERY_CONTENT = Object.freeze({
40682
40753
  action: 'Inspect the rejected paths in the workflow and correct the workspace before retrying.',
40683
40754
  retainedState: 'The normal commit and push steps were skipped. Verify the current state before retrying.',
40684
40755
  }),
40756
+ 'sdd-draft-case-identity-invalid': Object.freeze({
40757
+ impact: 'SDD publication stopped after one automatic repair: case IDs collide with an owning SDD or are ambiguous.',
40758
+ action: 'Review the draft tables; use distinct fully qualified case IDs and preserve the baseline inventory. Retry the same issue workflow.',
40759
+ retainedState: 'Existing answers and published SDDs were preserved; no draft was published. Publication checks do not establish runtime acceptance.',
40760
+ }),
40761
+ 'sdd-draft-case-budget-invalid': Object.freeze({
40762
+ impact: 'SDD publication stopped after one automatic repair: per-area allocations disagree with the distinct case inventory.',
40763
+ action: 'Review the draft tables; reconcile each area and the total with the enumerated cases. Retry the same issue workflow.',
40764
+ retainedState: 'Existing answers and published SDDs were preserved; no draft was published. Publication checks do not establish runtime acceptance.',
40765
+ }),
40766
+ 'sdd-draft-requirement-mapping-invalid': Object.freeze({
40767
+ impact: 'SDD publication stopped after one automatic repair: requirements and case mappings are incomplete or inconsistent.',
40768
+ action: 'Review the draft tables; map every requirement to defined cases and match the reverse links. Retry the same issue workflow.',
40769
+ retainedState: 'Existing answers and published SDDs were preserved; no draft was published. Publication checks do not establish runtime acceptance.',
40770
+ }),
40771
+ 'sdd-draft-repository-path-invalid': Object.freeze({
40772
+ impact: 'SDD publication stopped after one automatic repair: cited repository paths cannot be verified at the immutable base.',
40773
+ action: 'Review the draft tables; correct existing paths or explicitly declare intended new files. Retry the same issue workflow.',
40774
+ retainedState: 'Existing answers and published SDDs were preserved; no draft was published. Publication checks do not establish runtime acceptance.',
40775
+ }),
40685
40776
  'sdd-draft-format-invalid': Object.freeze({
40686
40777
  impact: 'SDD preparation stopped because the draft still lacked required headings or a numeric test budget after one automatic repair.',
40687
40778
  action: 'Retry SDD preparation with the canonical specification template and the explicit acceptance requirements.',
@@ -40744,6 +40835,21 @@ const ENGLISH_RECOVERY_CONTENT = Object.freeze({
40744
40835
  }),
40745
40836
  });
40746
40837
  const SPANISH_RECOVERY_CONTENT = Object.freeze({
40838
+ 'stored-configuration-schema-missing': Object.freeze({
40839
+ impact: 'La automatización se detuvo para la issue/PR #{issueNumber}: la configuración almacenada no tiene versión de esquema; se requiere la versión {expectedVersion}.',
40840
+ action: STORED_CONFIGURATION_ACTION_ES,
40841
+ retainedState: STORED_CONFIGURATION_RETAINED_ES,
40842
+ }),
40843
+ 'stored-configuration-schema-unsupported': Object.freeze({
40844
+ impact: 'La automatización se detuvo para la issue/PR #{issueNumber}: la versión de esquema almacenada {actualVersion} no es compatible; se requiere la versión {expectedVersion}.',
40845
+ action: STORED_CONFIGURATION_ACTION_ES,
40846
+ retainedState: STORED_CONFIGURATION_RETAINED_ES,
40847
+ }),
40848
+ 'stored-configuration-invalid': Object.freeze({
40849
+ impact: 'La automatización se detuvo para la issue/PR #{issueNumber}: la configuración almacenada, sus delimitadores o el valor del esquema no son válidos; se requiere un esquema válido de versión {expectedVersion}.',
40850
+ action: STORED_CONFIGURATION_ACTION_ES,
40851
+ retainedState: STORED_CONFIGURATION_RETAINED_ES,
40852
+ }),
40747
40853
  'closed-issue-reconciliation-failed': Object.freeze({
40748
40854
  impact: 'La limpieza de la issue sigue sin verificarse: {resultId}, fase {phase}; estado nativo {state}, motivo {reason}.',
40749
40855
  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.',
@@ -40759,6 +40865,26 @@ const SPANISH_RECOVERY_CONTENT = Object.freeze({
40759
40865
  action: 'Revisa las rutas rechazadas en la ejecución y corrige el espacio de trabajo antes de reintentar.',
40760
40866
  retainedState: 'Se omitieron los pasos normales de commit y push. Comprueba el estado actual antes de reintentar.',
40761
40867
  }),
40868
+ 'sdd-draft-case-identity-invalid': Object.freeze({
40869
+ impact: 'La publicación del SDD se detuvo tras un intento automático de corrección: los identificadores de casos coinciden con un SDD existente o son ambiguos.',
40870
+ action: 'Revisa las tablas del borrador; usa identificadores completos y distintos y conserva el inventario original. Reintenta el workflow de la misma incidencia.',
40871
+ retainedState: 'Se conservaron las respuestas y los SDD publicados; no se publicó ningún borrador. Estas comprobaciones no demuestran la aceptación en ejecución.',
40872
+ }),
40873
+ 'sdd-draft-case-budget-invalid': Object.freeze({
40874
+ impact: 'La publicación del SDD se detuvo tras un intento automático de corrección: las asignaciones por área no coinciden con el inventario de casos distintos.',
40875
+ action: 'Revisa las tablas del borrador; reconcilia cada área y el total con los casos enumerados. Reintenta el workflow de la misma incidencia.',
40876
+ retainedState: 'Se conservaron las respuestas y los SDD publicados; no se publicó ningún borrador. Estas comprobaciones no demuestran la aceptación en ejecución.',
40877
+ }),
40878
+ 'sdd-draft-requirement-mapping-invalid': Object.freeze({
40879
+ impact: 'La publicación del SDD se detuvo tras un intento automático de corrección: los requisitos y sus casos están incompletos o son inconsistentes.',
40880
+ action: 'Revisa las tablas del borrador; vincula cada requisito a casos definidos y comprueba los enlaces inversos. Reintenta el workflow de la misma incidencia.',
40881
+ retainedState: 'Se conservaron las respuestas y los SDD publicados; no se publicó ningún borrador. Estas comprobaciones no demuestran la aceptación en ejecución.',
40882
+ }),
40883
+ 'sdd-draft-repository-path-invalid': Object.freeze({
40884
+ impact: 'La publicación del SDD se detuvo tras un intento automático de corrección: no se pueden verificar las rutas citadas en la revisión base inmutable.',
40885
+ action: 'Revisa las tablas del borrador; corrige las rutas existentes o declara explícitamente los archivos nuevos previstos. Reintenta el workflow de la misma incidencia.',
40886
+ retainedState: 'Se conservaron las respuestas y los SDD publicados; no se publicó ningún borrador. Estas comprobaciones no demuestran la aceptación en ejecución.',
40887
+ }),
40762
40888
  'sdd-draft-format-invalid': Object.freeze({
40763
40889
  impact: 'La preparación del SDD se detuvo porque seguían faltando secciones obligatorias o un presupuesto numérico de pruebas tras un intento automático de corrección.',
40764
40890
  action: 'Reintenta la preparación del SDD con la plantilla canónica y los criterios de aceptación explícitos.',
@@ -40873,12 +40999,16 @@ exports.buildApplicationErrorPresentation = buildApplicationErrorPresentation;
40873
40999
  exports.renderApplicationErrorText = renderApplicationErrorText;
40874
41000
  exports.renderApplicationErrorMarkdown = renderApplicationErrorMarkdown;
40875
41001
  const application_error_message_catalog_1 = __nccwpck_require__(64809);
41002
+ // This trusted destination is inserted after localization, never supplied by a body or translation.
41003
+ const STORED_CONFIGURATION_RECOVERY_URL = 'https://docs.page/vypdev/copilot/security-operations/operations/troubleshooting#unsupported-stored-configuration';
40876
41004
  /** Shared semantic view model for terminal, GitHub, and API presentation. */
40877
41005
  function buildApplicationErrorPresentation(error, message = application_error_message_catalog_1.readEnglishApplicationErrorMessage) {
40878
41006
  const descriptor = error.recovery
40879
41007
  ? `error.recovery.${error.recovery.id}`
40880
41008
  : `error.${error.code}`;
40881
- const variables = error.recovery?.variables;
41009
+ const variables = error.recovery?.id.startsWith('stored-configuration-')
41010
+ ? { ...error.recovery.variables, recoveryGuide: STORED_CONFIGURATION_RECOVERY_URL }
41011
+ : error.recovery?.variables;
40882
41012
  return {
40883
41013
  impact: message(`${descriptor}.impact`, variables),
40884
41014
  code: error.code,
@@ -41920,6 +42050,7 @@ exports.BUGBOT_MESSAGE_IDS = Object.freeze([
41920
42050
  'bugbot.overflow.body',
41921
42051
  'bugbot.common.more',
41922
42052
  'bugbot.diagnostic.operationFailed',
42053
+ 'bugbot.diagnostic.findingMutationFailed',
41923
42054
  'bugbot.diagnostic.identityUnavailable',
41924
42055
  'bugbot.diagnostic.pullRequestCommentsFailed',
41925
42056
  'bugbot.diagnostic.reviewThreadsFailed',
@@ -42005,6 +42136,7 @@ const ENGLISH_MESSAGES = Object.freeze({
42005
42136
  'bugbot.overflow.heading': 'More findings (comment limit)',
42006
42137
  'bugbot.overflow.body': Object.freeze({ one: 'There is {count} more finding that was not published as an individual comment. Review locally or in the full diff to see the list.', other: 'There are {count} more findings that were not published as individual comments. Review locally or in the full diff to see the list.' }),
42007
42138
  'bugbot.common.more': Object.freeze({ one: 'and {count} more.', other: 'and {count} more.' }),
42139
+ 'bugbot.diagnostic.findingMutationFailed': 'Finding mutation failed: stage={stage}; operation={operation}; finding={findingId}; affected={affectedCount}; {providerStatus}; provider reference={providerReference}. Completed effects are retained. Correct access/contract errors before retrying; for transient failures restore provider availability, then recheck the same PR. Recheck reconciles existing reviews and threads.',
42008
42140
  'bugbot.diagnostic.operationFailed': 'Bugbot could not complete one or more finding mutations.',
42009
42141
  'bugbot.diagnostic.identityUnavailable': 'The authenticated Bugbot identity is unavailable.',
42010
42142
  'bugbot.diagnostic.pullRequestCommentsFailed': 'Unable to re-read pull request review comments.',
@@ -42094,6 +42226,7 @@ const SPANISH_MESSAGES = Object.freeze({
42094
42226
  'bugbot.overflow.heading': 'Más hallazgos (límite de comentarios)',
42095
42227
  'bugbot.overflow.body': Object.freeze({ one: 'Hay {count} hallazgo más que no se publicó como comentario individual. Revísalo localmente o en el diff completo para consultar la lista.', many: 'Hay {count} hallazgos más que no se publicaron como comentarios individuales. Revísalos localmente o en el diff completo para consultar la lista.', other: 'Hay {count} hallazgos más que no se publicaron como comentarios individuales. Revísalos localmente o en el diff completo para consultar la lista.' }),
42096
42228
  'bugbot.common.more': Object.freeze({ one: 'y {count} más.', many: 'y {count} más.', other: 'y {count} más.' }),
42229
+ 'bugbot.diagnostic.findingMutationFailed': 'Falló una mutación: fase={stage}; operación={operation}; hallazgo={findingId}; afectados={affectedCount}; {providerStatus}; referencia del proveedor={providerReference}. Se conservan los efectos completados. Corrige acceso/contrato antes de reintentar; para fallos transitorios restaura el proveedor y revisa la misma PR. La revisión reconcilia comentarios e hilos existentes.',
42097
42230
  'bugbot.diagnostic.operationFailed': 'Bugbot no pudo completar una o más mutaciones de hallazgos.',
42098
42231
  'bugbot.diagnostic.identityUnavailable': 'La identidad autenticada de Bugbot no está disponible.',
42099
42232
  'bugbot.diagnostic.pullRequestCommentsFailed': 'No se pudieron volver a leer los comentarios del review del pull request.',
@@ -42133,6 +42266,7 @@ async function resolveBugbotCatalog(locale, configuration, resolver) {
42133
42266
  }
42134
42267
  function renderBugbotDiagnostic(diagnostic, catalog) {
42135
42268
  switch (diagnostic.code) {
42269
+ case 'finding-mutation-failed': return catalog.message('bugbot.diagnostic.findingMutationFailed', { ...diagnostic.mutation });
42136
42270
  case 'operation-failed': return catalog.message('bugbot.diagnostic.operationFailed');
42137
42271
  case 'identity-unavailable': return catalog.message('bugbot.diagnostic.identityUnavailable');
42138
42272
  case 'snapshot-pull-request-comments-failed': return catalog.message('bugbot.diagnostic.pullRequestCommentsFailed');
@@ -42760,6 +42894,10 @@ function renderBugbotStatusCard(projection, catalogOrLocale, links) {
42760
42894
  facts.push(catalog.message('bugbot.coverage.omitted', { count: source.omittedItems }));
42761
42895
  if (source.truncatedItems > 0)
42762
42896
  facts.push(catalog.message('bugbot.coverage.truncated', { count: source.truncatedItems }));
42897
+ const truncatedIds = source.truncatedItemIds?.slice(0, 50)
42898
+ .filter(id => /^(?:issue:[0-9]+|review:[A-Za-z0-9_=-]+)$/.test(id) && id.length <= 160);
42899
+ if (truncatedIds?.length)
42900
+ facts.push(`truncated-source-ids=${truncatedIds.join(', ')}`);
42763
42901
  if (source.providerLimitReached)
42764
42902
  facts.push(catalog.message('bugbot.coverage.providerLimit'));
42765
42903
  return `- ${source.source}: ${source.status}; ${facts.join(', ')}`;
@@ -42849,9 +42987,21 @@ function normalizeHistoricalSnapshot(originalBody, analyzedHeadSha, catalog) {
42849
42987
  function renderFindingRow(finding) {
42850
42988
  const label = (0, github_comment_publication_policy_1.sanitizeAgentMarkdown)(finding.title || finding.id, 500).replace(/[\r\n]+/gu, ' ');
42851
42989
  const state = stateLabel(finding.state);
42990
+ const identity = finding.state === 'unknown'
42991
+ ? ` — ${renderFindingId(finding.id)}`
42992
+ : '';
42852
42993
  return finding.url
42853
- ? `- ${state} — [${label}](${finding.url})`
42854
- : `- ${state} — ${label}`;
42994
+ ? `- ${state} — [${label}](${finding.url})${identity}`
42995
+ : `- ${state} — ${label}${identity}`;
42996
+ }
42997
+ function renderFindingId(value) {
42998
+ const id = (0, github_comment_publication_policy_1.sanitizeAgentMarkdown)(value, 200).replace(/[\r\n]+/gu, ' ');
42999
+ // A delimiter longer than every embedded backtick run keeps links, images
43000
+ // and HTML inert even when the marker permits arbitrary Markdown punctuation.
43001
+ let delimiter = '`';
43002
+ while (id.includes(delimiter))
43003
+ delimiter += '`';
43004
+ return `${delimiter} ${id} ${delimiter}`;
42855
43005
  }
42856
43006
  function stateLabel(state) {
42857
43007
  return `[ ] ${state}`;
@@ -47706,6 +47856,8 @@ The setup runner profile selects placement; it does not install the project's la
47706
47856
 
47707
47857
  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
47858
 
47859
+ The optional repository-owned composite action prepares each candidate before verification. Setup creates .github/actions/copilot-verification-setup/action.yml only if missing and preserves an existing consumer action and its assets. The shared terminal/web assistant offers explicit activation, disabled by default. Customize the generated failing placeholder before enabling; setup generation and installer PRs do not prove runtime readiness. Review \`.github/actions/copilot-verification-setup/action.yml\` and its assets onto trusted main, update generated workflows, then enable \`VERIFICATION_SETUP=true\` (Action input \`verification-setup\`, disabled by default). GitHub Actions executes the trusted snapshot before each command with a fresh private HOME; candidate changes cannot replace it. Native post steps finish before profile cleanup. Setup failure blocks verification and commit/push. The local CLI cannot execute composite actions and fails closed when opted in. Read [repository-owned setup](https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-owned-setup).
47860
+
47709
47861
  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).
47710
47862
  `;
47711
47863
  }
@@ -47925,6 +48077,40 @@ function calculateReviewersStillNeeded(desiredCount, currentCount, confirmedCoun
47925
48077
  }
47926
48078
 
47927
48079
 
48080
+ /***/ }),
48081
+
48082
+ /***/ 81053:
48083
+ /***/ ((__unused_webpack_module, exports) => {
48084
+
48085
+ "use strict";
48086
+
48087
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
48088
+ exports.sddAnalysisStatusMarker = sddAnalysisStatusMarker;
48089
+ exports.renderSddAnalysisStatus = renderSddAnalysisStatus;
48090
+ function sddAnalysisStatusMarker(issueNumber) {
48091
+ return `<!-- copilot:sdd-analysis-status:v1 issue="${issueNumber}" -->`;
48092
+ }
48093
+ const reasons = {
48094
+ 'update-owner-mismatch': ['The update path does not belong to the selected catalog owner.', 'La ruta de actualización no pertenece al propietario seleccionado del catálogo.'],
48095
+ 'companion-owner-unknown': ['The companion owner is absent from the catalog.', 'El propietario del SDD complementario no existe en el catálogo.'],
48096
+ 'companion-path-registered': ['The companion path is already registered in the catalog.', 'La ruta del SDD complementario ya está registrada en el catálogo.'],
48097
+ 'new-owner-registered': ['The proposed new capability already exists in the catalog.', 'La capacidad propuesta como nueva ya existe en el catálogo.'],
48098
+ 'new-path-registered': ['The proposed new SDD path is already registered in the catalog.', 'La ruta propuesta como nueva ya está registrada en el catálogo.'],
48099
+ };
48100
+ /** Stateless diagnostic, deliberately separate from the validated readiness record. */
48101
+ function renderSddAnalysisStatus(issueNumber, locale, reason) {
48102
+ const spanish = /^es(?:-|$)/i.test(locale ?? '');
48103
+ const marker = sddAnalysisStatusMarker(issueNumber);
48104
+ if (!reason)
48105
+ return spanish
48106
+ ? `## Estado del análisis del SDD\n\nEl análisis posterior ha validado la propiedad. La publicación y la preparación de la rama siguen pendientes de sus comprobaciones.\n\n${marker}`
48107
+ : `## SDD analysis status\n\nA subsequent analysis validated ownership. Publication and branch readiness remain subject to their checks.\n\n${marker}`;
48108
+ return spanish
48109
+ ? `## Estado del SDD: análisis bloqueado\n\nNo se ha preparado ningún borrador ni publicación nueva. ${reasons[reason][1]}\n\n**Acción de mantenimiento:** Aclara en la misma issue el ID de capacidad del catálogo y la ruta: una actualización usa una ruta de ese propietario; un complemento usa un propietario existente y una ruta nueva; una capacidad nueva necesita ID y ruta sin registrar. Después vuelve a ejecutar el workflow original. Cada ejecución hace un solo análisis; no hay reparación ni reintento automático. Se conservan las respuestas, los SDD y las publicaciones anteriores.\n\n**Diagnóstico:** \`${reason}\`. La decisión rechazada no autoriza una rama ni la etiqueta de preparación.\n\n${marker}`
48110
+ : `## SDD work status: analysis blocked\n\nNo draft or new publication was prepared. ${reasons[reason][0]}\n\n**Maintainer action:** Clarify the catalog capability ID and path in this same issue: an update uses a path owned by that capability; a companion uses an existing owner and a new path; a new capability needs an unregistered ID and path. Then rerun the original workflow. Each invocation performs one analysis; there is no automatic repair or retry. Existing answers, SDDs and publications are retained.\n\n**Diagnostic:** \`${reason}\`. The rejected decision authorizes no branch or readiness label.\n\n${marker}`;
48111
+ }
48112
+
48113
+
47928
48114
  /***/ }),
47929
48115
 
47930
48116
  /***/ 2230:
@@ -48876,6 +49062,7 @@ exports.isSetupBatchInstallationReceipt = isSetupBatchInstallationReceipt;
48876
49062
  exports.parseSetupBatchOperation = parseSetupBatchOperation;
48877
49063
  exports.validSetupBatchAssetPath = validSetupBatchAssetPath;
48878
49064
  const setup_batch_1 = __nccwpck_require__(88308);
49065
+ const setup_verification_action_1 = __nccwpck_require__(33156);
48879
49066
  const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u;
48880
49067
  const sha = /^[a-f0-9]{40}$/u;
48881
49068
  const digest = /^[a-f0-9]{64}$/u;
@@ -48981,6 +49168,7 @@ function validSetupBatchAssetPath(path) {
48981
49168
  if (path.length > 240 || path.split('/').some(part => !part || part === '.' || part === '..') || /[^A-Za-z0-9_./-]/u.test(path))
48982
49169
  return false;
48983
49170
  return path === 'AGENTS.md' || path === '.agents/skills/copilot-repository-workflow/SKILL.md'
49171
+ || path === setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH
48984
49172
  || /^\.github\/(?:workflows|ISSUE_TEMPLATE)\/[A-Za-z0-9_.-]+\.(?:yml|yaml)$/u.test(path)
48985
49173
  || path === '.github/pull_request_template.md' || /^\.copilot\/(?:repository-profile|setup-manifest|runner-profile)\.json$/u.test(path)
48986
49174
  || path === '.copilot/AGENT_GUIDE.md' || path.startsWith('.copilot/setup-backups/');
@@ -49087,6 +49275,7 @@ function createDefaultSetupConfiguration() {
49087
49275
  choreTree: 'chore',
49088
49276
  issueManagedBranches: true,
49089
49277
  preBranchSdd: false,
49278
+ verificationSetup: false,
49090
49279
  reopenIssueOnPush: true,
49091
49280
  desiredAssigneesCount: 1,
49092
49281
  desiredReviewersCount: 1,
@@ -49243,6 +49432,7 @@ Object.defineProperty(exports, "buildSetupCredentialRequirements", ({ enumerable
49243
49432
  const locale_1 = __nccwpck_require__(15386);
49244
49433
  const issue_workflow_profile_1 = __nccwpck_require__(26744);
49245
49434
  const setup_issue_workflow_policy_1 = __nccwpck_require__(81182);
49435
+ const setup_verification_action_1 = __nccwpck_require__(33156);
49246
49436
  const repository_agent_guidance_policy_1 = __nccwpck_require__(67402);
49247
49437
  function buildSetupPlan(configuration, mergeQueueReadiness = [], approvalReadiness = []) {
49248
49438
  const workflowFiles = (0, setup_workflow_catalog_1.enabledSetupWorkflowFiles)((0, setup_issue_workflow_policy_1.effectiveIssueWorkflowFeatures)(configuration))
@@ -49254,6 +49444,7 @@ function buildSetupPlan(configuration, mergeQueueReadiness = [], approvalReadine
49254
49444
  .filter(file => configuration.features.release !== false || file !== 'release.yml')
49255
49445
  .filter(file => configuration.features.hotfix !== false || file !== 'hotfix.yml');
49256
49446
  const selectedFiles = [
49447
+ setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH,
49257
49448
  ...(configuration.runners && configuration.runners.mode !== 'retain' ? ['.copilot/runner-profile.json'] : []),
49258
49449
  ...workflowFiles.map(file => `workflows/${file}`),
49259
49450
  ...issueTemplateFiles.map(file => `ISSUE_TEMPLATE/${file}`),
@@ -49354,6 +49545,7 @@ function buildSetupRepositoryVariables(configuration) {
49354
49545
  add('CHORE_TREE', repository.choreTree);
49355
49546
  add('ISSUE_MANAGED_BRANCHES', repository.issueManagedBranches);
49356
49547
  add('PRE_BRANCH_SDD', repository.preBranchSdd);
49548
+ add('VERIFICATION_SETUP', repository.verificationSetup ?? false);
49357
49549
  add('REOPEN_ISSUE_ON_PUSH', repository.reopenIssueOnPush);
49358
49550
  add('DESIRED_ASSIGNEES_COUNT', repository.desiredAssigneesCount);
49359
49551
  add('DESIRED_REVIEWERS_COUNT', repository.desiredReviewersCount);
@@ -49416,6 +49608,7 @@ function buildSetupActionInputs(configuration) {
49416
49608
  'chore-tree': repository.choreTree,
49417
49609
  'issue-managed-branches': String(repository.issueManagedBranches),
49418
49610
  'pre-branch-sdd': String(repository.preBranchSdd),
49611
+ 'verification-setup': String(repository.verificationSetup ?? false),
49419
49612
  'reopen-issue-on-push': String(repository.reopenIssueOnPush),
49420
49613
  'desired-assignees-count': String(repository.desiredAssigneesCount),
49421
49614
  'desired-reviewers-count': String(repository.desiredReviewersCount),
@@ -49861,6 +50054,9 @@ function validateSetupConfiguration(configuration, options = {}) {
49861
50054
  || typeof configuration.repository.preBranchSdd !== 'boolean') {
49862
50055
  errors.push('issue-managed-branches and pre-branch-sdd must be boolean values.');
49863
50056
  }
50057
+ if (configuration.repository.verificationSetup !== undefined && typeof configuration.repository.verificationSetup !== 'boolean') {
50058
+ errors.push('verification-setup must be a boolean value.');
50059
+ }
49864
50060
  if (configuration.repository.preBranchSdd && !configuration.repository.issueManagedBranches) {
49865
50061
  errors.push('pre-branch-sdd requires issue-managed-branches.');
49866
50062
  }
@@ -50263,6 +50459,7 @@ const repositoryFields = [
50263
50459
  ['HOTFIX_TREE', 'hotfixTree'], ['RELEASE_TREE', 'releaseTree'],
50264
50460
  ['DOCS_TREE', 'docsTree'], ['CHORE_TREE', 'choreTree'],
50265
50461
  ['ISSUE_MANAGED_BRANCHES', 'issueManagedBranches'], ['PRE_BRANCH_SDD', 'preBranchSdd'],
50462
+ ['VERIFICATION_SETUP', 'verificationSetup'],
50266
50463
  ['REOPEN_ISSUE_ON_PUSH', 'reopenIssueOnPush'], ['DESIRED_ASSIGNEES_COUNT', 'desiredAssigneesCount'],
50267
50464
  ['DESIRED_REVIEWERS_COUNT', 'desiredReviewersCount'], ['INACTIVITY_THRESHOLD_HOURS', 'inactivityThresholdHours'],
50268
50465
  ['REPOSITORY_LOCALE', 'repositoryLocale'], ['ISSUES_LOCALE', 'issueLocale'],
@@ -50993,6 +51190,58 @@ function verificationRuntimeMatches(required, observed) {
50993
51190
  }
50994
51191
 
50995
51192
 
51193
+ /***/ }),
51194
+
51195
+ /***/ 65326:
51196
+ /***/ ((__unused_webpack_module, exports) => {
51197
+
51198
+ "use strict";
51199
+
51200
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
51201
+ exports.VerificationSetupError = exports.VERIFICATION_SETUP_HELP = exports.VERIFICATION_SETUP_LIMITS = exports.VERIFICATION_SETUP_PATH = exports.VERIFICATION_SETUP_DIRECTORY = void 0;
51202
+ exports.parseVerificationSetupResult = parseVerificationSetupResult;
51203
+ exports.VERIFICATION_SETUP_DIRECTORY = '.github/actions/copilot-verification-setup';
51204
+ exports.VERIFICATION_SETUP_PATH = `${exports.VERIFICATION_SETUP_DIRECTORY}/action.yml`;
51205
+ exports.VERIFICATION_SETUP_LIMITS = Object.freeze({ timeoutMs: 300000, resultBytes: 16384, scriptBytes: 65536, snapshotBytes: 262144, files: 32, requests: 20 });
51206
+ exports.VERIFICATION_SETUP_HELP = 'https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-owned-setup';
51207
+ /** Closed facts only. Provider/helper output and raw exception causes never cross this boundary. */
51208
+ class VerificationSetupError extends Error {
51209
+ constructor(reason, sourceSha, exitCode) {
51210
+ const sha = sourceSha && /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u.test(sourceSha) ? sourceSha : 'unavailable';
51211
+ const exit = Number.isInteger(exitCode) && exitCode >= 0 && exitCode <= 255 ? ` Exit status: ${exitCode}.` : '';
51212
+ const action = reason === 'native-workflow-required'
51213
+ ? 'Update the generated Copilot workflows and run this operation in GitHub Actions; the local CLI cannot execute composite actions.'
51214
+ : `Review ${exports.VERIFICATION_SETUP_PATH} on the trusted main branch and rerun.`;
51215
+ super(`Repository setup blocked verification (${reason}). ${action} Trusted source SHA: ${sha}.${exit} Verification, commit and push are withheld. Help: ${exports.VERIFICATION_SETUP_HELP}`);
51216
+ this.reason = reason;
51217
+ this.exitCode = exitCode;
51218
+ this.name = 'VerificationSetupError';
51219
+ }
51220
+ }
51221
+ exports.VerificationSetupError = VerificationSetupError;
51222
+ function record(value) {
51223
+ return !!value && typeof value === 'object' && !Array.isArray(value);
51224
+ }
51225
+ function pathString(value) {
51226
+ return typeof value === 'string' && value.length > 0 && value.length <= 2048
51227
+ && ![...value].some(character => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127);
51228
+ }
51229
+ /** Filesystem containment is checked by the adapter, after this closed schema is parsed. */
51230
+ function parseVerificationSetupResult(value) {
51231
+ if (!record(value) || value.schemaVersion !== 1 || Object.keys(value).some(key => !['schemaVersion', 'path', 'environment'].includes(key))) {
51232
+ throw new VerificationSetupError('result-invalid');
51233
+ }
51234
+ const paths = value.path === undefined ? [] : value.path;
51235
+ const environment = value.environment === undefined ? {} : value.environment;
51236
+ if (!Array.isArray(paths) || paths.length > 8 || !paths.every(pathString) || new Set(paths).size !== paths.length
51237
+ || !record(environment) || Object.keys(environment).some(key => key !== 'JAVA_HOME')
51238
+ || ('JAVA_HOME' in environment && !pathString(environment.JAVA_HOME))) {
51239
+ throw new VerificationSetupError('result-invalid');
51240
+ }
51241
+ return Object.freeze({ path: Object.freeze([...paths]), ...(environment.JAVA_HOME ? { javaHome: environment.JAVA_HOME } : {}) });
51242
+ }
51243
+
51244
+
50996
51245
  /***/ }),
50997
51246
 
50998
51247
  /***/ 43193:
@@ -51158,6 +51407,13 @@ class PullRequestReviewOperationError extends Error {
51158
51407
  super(buildMessage(operation, context));
51159
51408
  this.name = "PullRequestReviewOperationError";
51160
51409
  this.operation = operation;
51410
+ const status = context?.providerStatus;
51411
+ if (typeof status === 'number' && Number.isInteger(status) && status >= 400 && status <= 599) {
51412
+ this.providerStatus = status;
51413
+ }
51414
+ if (typeof context?.providerReference === 'string' && /^[A-Za-z0-9:-]{1,64}$/.test(context.providerReference)) {
51415
+ this.providerReference = context.providerReference;
51416
+ }
51161
51417
  }
51162
51418
  }
51163
51419
  exports.PullRequestReviewOperationError = PullRequestReviewOperationError;
@@ -51198,6 +51454,18 @@ function bindSddEvidenceReadPorts(ports) {
51198
51454
  }
51199
51455
 
51200
51456
 
51457
+ /***/ }),
51458
+
51459
+ /***/ 26509:
51460
+ /***/ ((__unused_webpack_module, exports) => {
51461
+
51462
+ "use strict";
51463
+
51464
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
51465
+ exports.DISABLED_VERIFICATION_SETUP = void 0;
51466
+ exports.DISABLED_VERIFICATION_SETUP = Object.freeze({ kind: 'disabled' });
51467
+
51468
+
51201
51469
  /***/ }),
51202
51470
 
51203
51471
  /***/ 84387:
@@ -53108,6 +53376,7 @@ async function runInitialSetupWorkflow(request, dependencies) {
53108
53376
  }
53109
53377
  (0, logging_ports_1.logInfo)('📋 Ensuring .github and copying setup files...');
53110
53378
  const workspaceSelection = {
53379
+ ...(request.verificationActionState ? { verificationActionState: request.verificationActionState } : {}),
53111
53380
  features: setupConfiguration?.features,
53112
53381
  setupConfiguration,
53113
53382
  ...(request.workflowUpdates.length > 0 ? {
@@ -53119,6 +53388,8 @@ async function runInitialSetupWorkflow(request, dependencies) {
53119
53388
  const filesResult = dependencies.setupWorkspacePort.prepare(workspaceSelection);
53120
53389
  mark('files', filesResult.copied > 0 ? 'completed' : 'skipped');
53121
53390
  steps.push(`✅ Setup files: ${filesResult.copied} copied, ${filesResult.skipped} already existed`);
53391
+ if (request.verificationActionState)
53392
+ steps.push(`✅ Verification setup action ${request.verificationActionState === 'create' ? 'created' : 'preserved'}; VERIFICATION_SETUP=${setupConfiguration?.repository.verificationSetup ?? false}. Customize and review on MAIN_BRANCH, then run a real verification.`);
53122
53393
  if (setupConfiguration?.manageRepositorySecrets && secretValues > 0)
53123
53394
  mark('secrets', 'in-progress');
53124
53395
  const secrets = await (0, setup_resource_provisioning_1.ensureRepositorySecrets)(request, dependencies, setupConfiguration, remoteConfiguration);
@@ -58131,6 +58402,8 @@ function projectInitialSetupContext(source) {
58131
58402
  ...(credentials ? { setupCredentials: deepFreezeCopy(credentials) } : {}),
58132
58403
  ...(remote ? { setupRemoteConfiguration: deepFreezeCopy(remote) } : {}),
58133
58404
  workflowUpdates: Object.freeze(asStringArray(source.inputs?.setupWorkflowUpdates)),
58405
+ ...(source.inputs?.setupVerificationActionState === 'create' || source.inputs?.setupVerificationActionState === 'preserve'
58406
+ ? { verificationActionState: source.inputs.setupVerificationActionState } : {}),
58134
58407
  });
58135
58408
  }
58136
58409
  function projectIssueCommentActionContext(source) {
@@ -58636,6 +58909,7 @@ exports.draftSddMarkdown = draftSddMarkdown;
58636
58909
  const application_error_1 = __nccwpck_require__(75999);
58637
58910
  const pre_branch_sdd_1 = __nccwpck_require__(34730);
58638
58911
  const agent_response_length_failure_1 = __nccwpck_require__(28528);
58912
+ const sdd_draft_consistency_1 = __nccwpck_require__(27910);
58639
58913
  /** Size and typed format failures share one regeneration; the writer still validates every candidate. */
58640
58914
  async function draftSddMarkdown(agent, configuration, plan, prompt, validate) {
58641
58915
  const maximum = plan.action === 'update' ? pre_branch_sdd_1.SDD_MAX_UPDATE_CHARACTERS : pre_branch_sdd_1.SDD_MAX_DRAFT_CHARACTERS;
@@ -58647,13 +58921,13 @@ async function draftSddMarkdown(agent, configuration, plan, prompt, validate) {
58647
58921
  };
58648
58922
  let problem = 'size';
58649
58923
  let formatReason = 'required-heading';
58650
- const contractPrompt = `${prompt}\n\nDraft contract: keep the complete draft within ${maximum} characters; aim for ${target} characters. Preserve the same owner, decisions and requirements. Include these literal canonical heading prefixes as Markdown headings, with the shown capitalization:\n${pre_branch_sdd_1.SDD_REQUIRED_HEADINGS.join('\n')}\nUse the canonical numeric test-budget table in section 14: Area | Minimum distinct cases | Behaviors/risks covered. Every allocation and the Total must be a positive integer, and the Total must equal the sum of the allocations. A justified positive integer sentence of distinct tests or cases is also accepted. Return only the required JSON.`;
58924
+ const contractPrompt = `${prompt}\n\nDraft contract: keep the complete draft within ${maximum} characters; aim for ${target} characters. Preserve the same owner, decisions and requirements. Include these literal canonical heading prefixes as Markdown headings, with the shown capitalization:\n${pre_branch_sdd_1.SDD_REQUIRED_HEADINGS.join('\n')}\nUse the canonical numeric test-budget table in section 14: Area | Minimum distinct cases | Behaviors/risks covered. Every allocation and the Total must be a positive integer, and the Total must equal the sum of the allocations. Return only the required JSON.`;
58651
58925
  for (let attempt = 0; attempt < 2; attempt++) {
58652
58926
  let value;
58653
58927
  try {
58654
58928
  value = await agent.query({
58655
58929
  configuration, agentId: 'pre-branch-sdd-draft',
58656
- prompt: attempt === 0 ? contractPrompt : `${contractPrompt}\n\n${problem === 'size' ? `The previous response exceeded the ${maximum}-character draft limit.` : `The previous response failed the required SDD ${formatReason} contract.`} Regenerate a concise complete draft for this same owner and plan. Use the exact numbered canonical headings from the supplied template. Preserve all resolved requirements, architecture, documentation and acceptance. Do not change ownership or truncate a requirement.`,
58930
+ prompt: `${attempt === 0 ? contractPrompt : `${contractPrompt}\n\n${problem === 'size' ? `The previous response exceeded the ${maximum}-character draft limit.` : `The previous response failed the required SDD ${formatReason} contract.`} Regenerate a concise complete draft for this same owner and plan. Use the exact numbered canonical headings from the supplied template. Preserve all resolved requirements, architecture, documentation and acceptance. Do not change ownership or truncate a requirement.`}\n\n${sdd_draft_consistency_1.SDD_CONSISTENCY_PROMPT}`,
58657
58931
  options: { expectJson: true, schemaName: 'pre_branch_sdd_draft', schema },
58658
58932
  });
58659
58933
  }
@@ -58687,12 +58961,21 @@ async function draftSddMarkdown(agent, configuration, plan, prompt, validate) {
58687
58961
  }
58688
58962
  if (problem === 'format')
58689
58963
  throw new application_error_1.ApplicationError('validation.invalid-input', `The SDD draft still violates its ${formatReason} format contract after one bounded repair.`, {
58690
- recovery: { id: 'sdd-draft-format-invalid', variables: {} },
58964
+ recovery: { id: consistencyRecovery(formatReason), variables: {} },
58691
58965
  });
58692
58966
  throw new application_error_1.ApplicationError('validation.invalid-input', 'The SDD draft exceeded its size limit after one bounded repair.', {
58693
58967
  recovery: { id: 'sdd-draft-size-exceeded', variables: {} },
58694
58968
  });
58695
58969
  }
58970
+ function consistencyRecovery(reason) {
58971
+ switch (reason) {
58972
+ case 'case-identity': return 'sdd-draft-case-identity-invalid';
58973
+ case 'case-budget': return 'sdd-draft-case-budget-invalid';
58974
+ case 'requirement-mapping': return 'sdd-draft-requirement-mapping-invalid';
58975
+ case 'repository-path': return 'sdd-draft-repository-path-invalid';
58976
+ default: return 'sdd-draft-format-invalid';
58977
+ }
58978
+ }
58696
58979
 
58697
58980
 
58698
58981
  /***/ }),
@@ -58710,8 +58993,10 @@ const issue_start_policy_1 = __nccwpck_require__(90332);
58710
58993
  const pre_branch_sdd_1 = __nccwpck_require__(34730);
58711
58994
  const recommendation_policy_1 = __nccwpck_require__(39410);
58712
58995
  const logging_ports_1 = __nccwpck_require__(6152);
58996
+ const sdd_analysis_status_policy_1 = __nccwpck_require__(81053);
58713
58997
  const application_error_1 = __nccwpck_require__(75999);
58714
58998
  const pre_branch_sdd_draft_workflow_1 = __nccwpck_require__(93454);
58999
+ const sdd_draft_consistency_1 = __nccwpck_require__(27910);
58715
59000
  const ANALYSIS_SCHEMA = {
58716
59001
  type: 'object',
58717
59002
  properties: {
@@ -58832,11 +59117,21 @@ class PreBranchSddGateUseCase {
58832
59117
  });
58833
59118
  const analysisValue = asRecord(analysis);
58834
59119
  const owners = new Map(snapshot.capabilities.map(capability => [capability.id, capability.specs]));
58835
- const plan = (0, pre_branch_sdd_1.parseSddPlan)(analysisValue, owners);
59120
+ let plan;
59121
+ try {
59122
+ plan = (0, pre_branch_sdd_1.parseSddPlan)(analysisValue, owners);
59123
+ }
59124
+ catch (error) {
59125
+ if (!(error instanceof pre_branch_sdd_1.SddOwnershipFailure))
59126
+ throw error;
59127
+ await this.writeAnalysisStatus(context, allComments, error.reason);
59128
+ throw new application_error_1.ApplicationError('provider.contract-invalid', `${error.message} Clarify the catalog owner/path in the same issue and rerun the original workflow. No automatic retry was attempted.`);
59129
+ }
58836
59130
  if (card?.record.branchName && (plan.action !== 'update'
58837
59131
  || plan.path !== card.record.plan.path || plan.capabilityId !== card.record.plan.capabilityId)) {
58838
59132
  throw new Error('An existing linked branch can only revise its owning SDD on the same path.');
58839
59133
  }
59134
+ await this.writeAnalysisStatus(context, allComments);
58840
59135
  const round = publicationRetry ? card.record.round
58841
59136
  : card?.record.phase === 'awaiting-answer' && card.record.issueDigest === digest && !staleAwaiting
58842
59137
  ? card.record.round + (plan.questions.length > 0 ? 1 : 0) : 1;
@@ -58856,9 +59151,19 @@ class PreBranchSddGateUseCase {
58856
59151
  const currentSdd = plan.action === 'update' ? await this.workspace.readSdd(snapshot.baseSha, plan.path) : undefined;
58857
59152
  if (plan.action === 'update' && !currentSdd)
58858
59153
  throw new Error('The catalogued SDD owner is missing from the selected base.');
59154
+ const ownerDocuments = [];
59155
+ for (const path of snapshot.capabilities.find(capability => capability.id === plan.capabilityId)?.specs ?? []) {
59156
+ const markdown = path === plan.path && currentSdd ? currentSdd : await this.workspace.readSdd(snapshot.baseSha, path);
59157
+ if (!markdown)
59158
+ throw new Error('A catalogued owning SDD is unavailable at the selected immutable base.');
59159
+ ownerDocuments.push({ path, markdown });
59160
+ }
59161
+ const reservedCases = JSON.stringify((0, sdd_draft_consistency_1.reservedSddCaseIds)(ownerDocuments));
59162
+ if (reservedCases.length > 30000)
59163
+ throw new Error('The owning SDD case inventory exceeds the bounded drafting context; maintainer review is required.');
58859
59164
  const newCapability = plan.action === 'new' ? parseNewCapability(analysisValue.newCapability, plan) : undefined;
58860
59165
  let prepared;
58861
- await (0, pre_branch_sdd_draft_workflow_1.draftSddMarkdown)(this.agent, context.agentConfiguration, plan, buildDraftPrompt(context, snapshot, plan, answers, currentSdd), async (markdown) => {
59166
+ await (0, pre_branch_sdd_draft_workflow_1.draftSddMarkdown)(this.agent, context.agentConfiguration, plan, `${buildDraftPrompt(context, snapshot, plan, answers, currentSdd)}\n\nCase IDs reserved across every owning SDD at ${snapshot.baseSha}:\n${reservedCases}`, async (markdown) => {
58862
59167
  prepared = await this.workspace.validateDraft(snapshot, plan, markdown, newCapability);
58863
59168
  });
58864
59169
  if (!prepared)
@@ -58948,6 +59253,20 @@ class PreBranchSddGateUseCase {
58948
59253
  else
58949
59254
  await this.comments.updateComment(issueNumber, cardId, body);
58950
59255
  }
59256
+ async writeAnalysisStatus(context, comments, reason) {
59257
+ const marker = (0, sdd_analysis_status_policy_1.sddAnalysisStatusMarker)(context.issueNumber);
59258
+ const prior = comments.filter(comment => comment.user?.login?.toLowerCase() === context.tokenUser.toLowerCase()
59259
+ && comment.body?.includes(marker)).sort((a, b) => b.id - a.id)[0];
59260
+ if (!reason && !prior)
59261
+ return;
59262
+ const body = (0, sdd_analysis_status_policy_1.renderSddAnalysisStatus)(context.issueNumber, context.issueLocale, reason);
59263
+ if (prior) {
59264
+ if (prior.body !== body)
59265
+ await this.comments.updateComment(context.issueNumber, prior.id, body);
59266
+ }
59267
+ else
59268
+ await this.comments.addComment(context.issueNumber, body);
59269
+ }
58951
59270
  async assertFresh(context, expectedBaseSha, sourceBranch) {
58952
59271
  const [liveBody, liveTitle, snapshot] = await Promise.all([
58953
59272
  this.descriptions.getDescription(context.issueNumber),
@@ -59708,7 +60027,7 @@ function partitionFailureCategory(error) {
59708
60027
  return error instanceof Error ? error.name : 'unknown';
59709
60028
  }
59710
60029
  function suppressDismissedFindings(execution, context, prepared) {
59711
- const activeFindings = (prepared.activeFindings ?? prepared.toPublish).filter((finding) => {
60030
+ const activeFindings = (0, finding_1.retainExistingFindingIds)(prepared.activeFindings ?? prepared.toPublish, context.existingByFindingId).filter((finding) => {
59712
60031
  const existing = (0, finding_1.findExistingFindingInfo)(context.existingByFindingId, finding);
59713
60032
  return existing?.issue?.resolution !== 'dismissed' && existing?.pullRequest?.resolution !== 'dismissed';
59714
60033
  });
@@ -59728,6 +60047,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
59728
60047
  exports.applyDetectedFindings = applyDetectedFindings;
59729
60048
  const mark_findings_resolved_use_case_1 = __nccwpck_require__(96963);
59730
60049
  const publish_findings_use_case_1 = __nccwpck_require__(88442);
60050
+ const bugbot_mutation_error_1 = __nccwpck_require__(82937);
59731
60051
  const pull_request_review_errors_1 = __nccwpck_require__(46445);
59732
60052
  async function applyDetectedFindings(operation, context, prepared, publicationPorts, resolutionPorts, catalog) {
59733
60053
  try {
@@ -59743,7 +60063,7 @@ async function applyDetectedFindings(operation, context, prepared, publicationPo
59743
60063
  });
59744
60064
  }
59745
60065
  catch (error) {
59746
- const publicationError = error instanceof pull_request_review_errors_1.PullRequestReviewOperationError
60066
+ const publicationError = error instanceof bugbot_mutation_error_1.BugbotMutationError || error instanceof pull_request_review_errors_1.PullRequestReviewOperationError
59747
60067
  ? error
59748
60068
  : new Error("Unable to publish findings.");
59749
60069
  return [publicationError];
@@ -60294,6 +60614,7 @@ function buildPreviousFindingsContext(previousFindings) {
60294
60614
  `;
60295
60615
  const suffix = `
60296
60616
  **Your task 2:** For each finding above, analyze the current code and decide:
60617
+ - Trace the original failure precondition through current callers, validation helpers and effective configuration, including modules outside the original anchor. A retained finding is not proof that its old explanation is still true. Reuse its exact id if reporting the same defect again; do not create a second report for it.
60297
60618
  - If the problem **still exists** (same code or same issue present): do **not** include it in \`resolved_findings\`.
60298
60619
  - If the problem **no longer applies** (e.g. that code was removed or refactored away): include \`{ "id": "<exact id>", "resolution": "obsolete" }\` in \`resolved_findings\`.
60299
60620
  - If the problem **has been fixed** (code was changed and the issue is resolved): include \`{ "id": "<exact id>", "resolution": "fixed" }\` in \`resolved_findings\`.
@@ -60413,6 +60734,10 @@ function buildReviewConversationContext(issueComments, commentsByPullRequest, bo
60413
60734
  omitted,
60414
60735
  truncated: chronological.filter((entry) => entry.truncated).length,
60415
60736
  retained: chronological.length,
60737
+ ...(chronological.some(entry => entry.truncated) ? {
60738
+ truncatedItemIds: chronological.filter(entry => entry.truncated)
60739
+ .map(entry => entry.providerId).filter(id => /^(?:issue:[0-9]+|review:[A-Za-z0-9_=-]+)$/.test(id) && id.length <= 160),
60740
+ } : {}),
60416
60741
  };
60417
60742
  }
60418
60743
  function appendConversationEntry(entries, author, kind, body, createdAt, providerId) {
@@ -61904,6 +62229,7 @@ async function loadBugbotContext(request, ports, resolvedPreflight) {
61904
62229
  itemsFetched: conversationContext.retained + conversationContext.omitted,
61905
62230
  omittedItems: conversationContext.omitted,
61906
62231
  truncatedItems: conversationContext.truncated,
62232
+ ...(conversationContext.truncatedItemIds ? { truncatedItemIds: conversationContext.truncatedItemIds } : {}),
61907
62233
  limitReached: conversationContext.omitted > 0 || conversationContext.truncated > 0,
61908
62234
  },
61909
62235
  {
@@ -62105,11 +62431,11 @@ Object.defineProperty(exports, "markFindingsResolved", ({ enumerable: true, get:
62105
62431
 
62106
62432
  Object.defineProperty(exports, "__esModule", ({ value: true }));
62107
62433
  exports.markFindingsResolved = markFindingsResolved;
62108
- const pull_request_review_errors_1 = __nccwpck_require__(46445);
62109
62434
  const logging_ports_1 = __nccwpck_require__(6152);
62110
62435
  const resolve_issue_finding_1 = __nccwpck_require__(35300);
62111
62436
  const resolve_pull_request_finding_1 = __nccwpck_require__(64567);
62112
62437
  const review_state_1 = __nccwpck_require__(79200);
62438
+ const bugbot_mutation_error_1 = __nccwpck_require__(82937);
62113
62439
  const application_error_1 = __nccwpck_require__(75999);
62114
62440
  async function markFindingsResolved(param) {
62115
62441
  const errors = [];
@@ -62137,8 +62463,8 @@ async function repairExistingPullRequestFinding(ports, operation, findingId, des
62137
62463
  try {
62138
62464
  await ports.pullRequestComments.unresolvePullRequestReviewThread(destination.pullRequestNumber, destination.commentIdentity);
62139
62465
  }
62140
- catch {
62141
- addResolutionError(errors, 'pull request');
62466
+ catch (cause) {
62467
+ addResolutionError(errors, 'pull request', findingId, cause);
62142
62468
  }
62143
62469
  }
62144
62470
  }
@@ -62152,7 +62478,7 @@ async function resolveIssueIfNeeded(param, findingId, destination, errors) {
62152
62478
  return;
62153
62479
  const comment = param.context.issueComments.find(item => item.id === destination.commentId);
62154
62480
  if (comment?.body == null) {
62155
- addResolutionError(errors, 'issue');
62481
+ addResolutionError(errors, 'issue', findingId);
62156
62482
  return;
62157
62483
  }
62158
62484
  try {
@@ -62163,8 +62489,8 @@ async function resolveIssueIfNeeded(param, findingId, destination, errors) {
62163
62489
  resolution: param.resolvedFindingResolutions?.get(findingId),
62164
62490
  }, param.catalog);
62165
62491
  }
62166
- catch {
62167
- addResolutionError(errors, 'issue');
62492
+ catch (cause) {
62493
+ addResolutionError(errors, 'issue', findingId, cause);
62168
62494
  }
62169
62495
  }
62170
62496
  async function tryResolvePullRequestFinding(ports, findingId, destination, errors, resolution, catalog) {
@@ -62176,17 +62502,14 @@ async function tryResolvePullRequestFinding(ports, findingId, destination, error
62176
62502
  resolution,
62177
62503
  }, catalog);
62178
62504
  }
62179
- catch {
62180
- addResolutionError(errors, 'pull request');
62505
+ catch (cause) {
62506
+ addResolutionError(errors, 'pull request', findingId, cause);
62181
62507
  }
62182
62508
  }
62183
- function addResolutionError(errors, destination) {
62184
- const cause = destination === 'pull request'
62185
- ? new pull_request_review_errors_1.PullRequestReviewOperationError('mark-resolved')
62186
- : new Error('Unable to mark an issue finding as resolved.');
62187
- const semanticError = new application_error_1.ApplicationError('provider.unavailable', destination === 'pull request'
62188
- ? 'Unable to mark a pull request finding as resolved.'
62189
- : 'Unable to mark an issue finding as resolved.', { cause });
62509
+ function addResolutionError(errors, destination, findingId, cause) {
62510
+ const semanticError = destination === 'pull request'
62511
+ ? (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'resolution', [findingId], 'mark-resolved')
62512
+ : new application_error_1.ApplicationError('provider.unavailable', 'Unable to mark an issue finding as resolved.');
62190
62513
  (0, logging_ports_1.logError)(semanticError);
62191
62514
  errors.push(semanticError);
62192
62515
  }
@@ -62439,6 +62762,7 @@ function isRecord(value) {
62439
62762
  */
62440
62763
  Object.defineProperty(exports, "__esModule", ({ value: true }));
62441
62764
  exports.publishFindings = publishFindings;
62765
+ const bugbot_mutation_error_1 = __nccwpck_require__(82937);
62442
62766
  const finding_1 = __nccwpck_require__(31011);
62443
62767
  const publish_issue_finding_comment_1 = __nccwpck_require__(84950);
62444
62768
  const publish_pr_review_comments_1 = __nccwpck_require__(50352);
@@ -62457,12 +62781,17 @@ async function publishFindings(param) {
62457
62781
  catalog,
62458
62782
  })
62459
62783
  : undefined;
62460
- for (const finding of findings) {
62784
+ for (const finding of (0, finding_1.retainExistingFindingIds)(findings, existingByFindingId)) {
62461
62785
  if (operation.target.issueNumber > 0 && !reviewPublisher) {
62462
62786
  await (0, publish_issue_finding_comment_1.publishIssueFindingComment)(ports.issueComments, operation.target.issueNumber, finding, (0, finding_1.findExistingFindingInfo)(existingByFindingId, finding), commitSha, catalog);
62463
62787
  }
62464
62788
  if (reviewPublisher) {
62465
- await reviewPublisher.publish(finding, (0, finding_1.findExistingFindingInfo)(existingByFindingId, finding));
62789
+ try {
62790
+ await reviewPublisher.publish(finding, (0, finding_1.findExistingFindingInfo)(existingByFindingId, finding));
62791
+ }
62792
+ catch (cause) {
62793
+ throw (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'publication', [finding.id], 'publish-comments');
62794
+ }
62466
62795
  }
62467
62796
  }
62468
62797
  await reviewPublisher?.flush(overflowCount, overflowTitles);
@@ -62534,6 +62863,7 @@ ${catalog.message('bugbot.overflow.body', { count: `**${overflowCount}**` }, ove
62534
62863
 
62535
62864
  Object.defineProperty(exports, "__esModule", ({ value: true }));
62536
62865
  exports.PullRequestReviewCommentPublisher = void 0;
62866
+ const bugbot_mutation_error_1 = __nccwpck_require__(82937);
62537
62867
  const bugbot_finding_marker_policy_1 = __nccwpck_require__(98024);
62538
62868
  const path_validation_1 = __nccwpck_require__(70124);
62539
62869
  const logging_ports_1 = __nccwpck_require__(6152);
@@ -62605,11 +62935,16 @@ class PullRequestReviewCommentPublisher {
62605
62935
  if (this.findingsToCreate.length === 0 && overflowCount === 0)
62606
62936
  return;
62607
62937
  const { repository, operation, openPrNumber, prContext } = this.options;
62608
- await repository.createReviewWithComments(openPrNumber, prContext.prHeadSha, buildReviewSummary(this.findingsToCreate, this.commentsToCreate.length, this.unanchoredBodies, overflowCount, overflowTitles, operation.analysis.reviewConfiguration.traceRules
62609
- ? this.options.ruleSources ?? []
62610
- : [], operation.analysis.reviewConfiguration.traceRules
62611
- ? this.options.omittedRuleCount ?? 0
62612
- : 0, prContext.prHeadSha, this.catalog), this.commentsToCreate);
62938
+ try {
62939
+ await repository.createReviewWithComments(openPrNumber, prContext.prHeadSha, buildReviewSummary(this.findingsToCreate, this.commentsToCreate.length, this.unanchoredBodies, overflowCount, overflowTitles, operation.analysis.reviewConfiguration.traceRules
62940
+ ? this.options.ruleSources ?? []
62941
+ : [], operation.analysis.reviewConfiguration.traceRules
62942
+ ? this.options.omittedRuleCount ?? 0
62943
+ : 0, prContext.prHeadSha, this.catalog), this.commentsToCreate);
62944
+ }
62945
+ catch (cause) {
62946
+ throw (0, bugbot_mutation_error_1.bugbotMutationError)(cause, 'publication', this.findingsToCreate.map(finding => finding.id), 'publish-comments', this.findingsToCreate.length + overflowCount);
62947
+ }
62613
62948
  }
62614
62949
  get catalog() {
62615
62950
  return this.options.catalog ?? (0, bugbot_message_catalog_1.resolveStaticBugbotCatalog)(this.options.operation.locale.pullRequest);
@@ -62765,6 +63100,8 @@ async function queryBugbotPartitionFindings(repository, configuration, prompt, t
62765
63100
 
62766
63101
  Object.defineProperty(exports, "__esModule", ({ value: true }));
62767
63102
  exports.reconcileBugbotReviewState = reconcileBugbotReviewState;
63103
+ const bugbot_mutation_error_1 = __nccwpck_require__(82937);
63104
+ const finding_1 = __nccwpck_require__(31011);
62768
63105
  const review_projection_1 = __nccwpck_require__(80859);
62769
63106
  const bugbot_reconciliation_policy_1 = __nccwpck_require__(78128);
62770
63107
  const bugbot_provider_projection_policy_1 = __nccwpck_require__(85821);
@@ -62795,11 +63132,12 @@ async function reconcileBugbotReviewState(input) {
62795
63132
  };
62796
63133
  }
62797
63134
  const snapshot = snapshotResult.snapshot;
63135
+ const activeFindings = (0, finding_1.retainExistingFindingIds)(input.activeFindings, input.loadedContext.existingByFindingId);
63136
+ const expectedPublishedFindings = (0, finding_1.retainExistingFindingIds)(input.expectedPublishedFindings ?? input.activeFindings, input.loadedContext.existingByFindingId);
62798
63137
  const diagnostics = [
62799
- ...(input.mutationErrors ?? []).map((error) => ({
62800
- code: 'operation-failed',
62801
- operatorMessage: toSafeOperationMessage(error),
62802
- })),
63138
+ ...(input.mutationErrors ?? []).map((error) => error instanceof bugbot_mutation_error_1.BugbotMutationError
63139
+ ? { code: 'finding-mutation-failed', mutation: error.diagnostic }
63140
+ : { code: 'operation-failed', operatorMessage: toSafeOperationMessage(error) }),
62803
63141
  ...(!input.target.trustedAuthorLogin?.trim()
62804
63142
  ? [{ code: 'identity-unavailable' }]
62805
63143
  : []),
@@ -62808,7 +63146,7 @@ async function reconcileBugbotReviewState(input) {
62808
63146
  const providerProjection = (0, bugbot_provider_projection_policy_1.projectBugbotProviderEvidence)({
62809
63147
  snapshot,
62810
63148
  trustedAuthorLogin: input.target.trustedAuthorLogin,
62811
- activeFindings: input.activeFindings,
63149
+ activeFindings,
62812
63150
  existingByFindingId: input.loadedContext.existingByFindingId,
62813
63151
  });
62814
63152
  const plan = (0, bugbot_reconciliation_policy_1.buildBugbotReconciliationPlan)({
@@ -62818,8 +63156,8 @@ async function reconcileBugbotReviewState(input) {
62818
63156
  id,
62819
63157
  (0, bugbot_finding_marker_policy_1.extractTitleFromBody)(fullBody) || id,
62820
63158
  ])),
62821
- activeFindings: input.activeFindings,
62822
- expectedPublishedFindings: input.expectedPublishedFindings ?? input.activeFindings,
63159
+ activeFindings,
63160
+ expectedPublishedFindings,
62823
63161
  diagnostics,
62824
63162
  coverage: input.loadedContext.coverage,
62825
63163
  });
@@ -63323,14 +63661,16 @@ function toPresentationFailure(diagnostic) {
63323
63661
  const message = (0, bugbot_message_catalog_1.bugbotDiagnosticOperatorMessage)(diagnostic);
63324
63662
  return {
63325
63663
  diagnostic,
63326
- error: diagnostic.code === 'review-updates-pending'
63327
- ? new application_error_1.ApplicationError('workflow.presentation-pending', message, {
63328
- recovery: {
63329
- id: 'bugbot-review-blocks-pending',
63330
- variables: { pendingCount: diagnostic.count },
63331
- },
63332
- })
63333
- : new Error(message),
63664
+ error: diagnostic.code === 'finding-mutation-failed'
63665
+ ? new application_error_1.ApplicationError(diagnostic.mutation.errorCode, message)
63666
+ : diagnostic.code === 'review-updates-pending'
63667
+ ? new application_error_1.ApplicationError('workflow.presentation-pending', message, {
63668
+ recovery: {
63669
+ id: 'bugbot-review-blocks-pending',
63670
+ variables: { pendingCount: diagnostic.count },
63671
+ },
63672
+ })
63673
+ : new Error(message),
63334
63674
  };
63335
63675
  }
63336
63676
  function report(projection, reviewUpdates, pendingReviewUpdates, statusCardOperation, errors) {
@@ -63443,6 +63783,7 @@ exports.runVerifyCommands = runVerifyCommands;
63443
63783
  const logging_ports_1 = __nccwpck_require__(6152);
63444
63784
  const verify_command_policy_1 = __nccwpck_require__(96031);
63445
63785
  const verification_runtime_policy_1 = __nccwpck_require__(89347);
63786
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
63446
63787
  async function runVerifyCommands(commands, execute) {
63447
63788
  for (const command of commands) {
63448
63789
  const result = await executeVerifyCommand(command, execute);
@@ -63462,7 +63803,7 @@ async function executeVerifyCommand(command, execute) {
63462
63803
  : { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
63463
63804
  }
63464
63805
  catch (error) {
63465
- if (error instanceof verification_runtime_policy_1.VerificationPrerequisiteError) {
63806
+ if (error instanceof verification_runtime_policy_1.VerificationPrerequisiteError || error instanceof verification_setup_policy_1.VerificationSetupError) {
63466
63807
  return { success: false, failedCommand: formatCommandForDiagnostics(parsed),
63467
63808
  error: `${error.message} Verification command: ${formatCommandForDiagnostics(parsed)}.` };
63468
63809
  }
@@ -68785,9 +69126,16 @@ exports.APPLICATION_ERROR_RECOVERY_IDS = Object.freeze([
68785
69126
  'branch-sync-resolution-invalid',
68786
69127
  'sdd-draft-size-exceeded',
68787
69128
  'sdd-draft-format-invalid',
69129
+ 'sdd-draft-case-identity-invalid',
69130
+ 'sdd-draft-case-budget-invalid',
69131
+ 'sdd-draft-requirement-mapping-invalid',
69132
+ 'sdd-draft-repository-path-invalid',
68788
69133
  'workspace-changes-rejected',
68789
69134
  'closed-issue-reconciliation-failed',
68790
69135
  'approval-evidence-read-failed',
69136
+ 'stored-configuration-schema-missing',
69137
+ 'stored-configuration-schema-unsupported',
69138
+ 'stored-configuration-invalid',
68791
69139
  ]);
68792
69140
  const PRESERVED_STATE = 'Existing persisted state and completed external effects were preserved.';
68793
69141
  const UNCHANGED_STATE = 'No new state or external effect was created.';
@@ -68979,6 +69327,9 @@ class ApplicationError extends Error {
68979
69327
  exports.ApplicationError = ApplicationError;
68980
69328
  _ApplicationError_cause = new WeakMap();
68981
69329
  const RECOVERY_VARIABLE_KEYS = Object.freeze({
69330
+ 'stored-configuration-schema-missing': Object.freeze(['issueNumber', 'expectedVersion']),
69331
+ 'stored-configuration-schema-unsupported': Object.freeze(['issueNumber', 'expectedVersion', 'actualVersion']),
69332
+ 'stored-configuration-invalid': Object.freeze(['issueNumber', 'expectedVersion']),
68982
69333
  'closed-issue-reconciliation-failed': Object.freeze(['resultId', 'phase', 'state', 'reason', 'changed', 'remaining']),
68983
69334
  'approval-evidence-read-failed': Object.freeze(['operation', 'reason', 'permission']),
68984
69335
  'pull-request-link-restored': Object.freeze([]),
@@ -68993,6 +69344,10 @@ const RECOVERY_VARIABLE_KEYS = Object.freeze({
68993
69344
  'branch-sync-resolution-invalid': Object.freeze(['validationCode', 'command']),
68994
69345
  'sdd-draft-size-exceeded': Object.freeze([]),
68995
69346
  'sdd-draft-format-invalid': Object.freeze([]),
69347
+ 'sdd-draft-case-identity-invalid': Object.freeze([]),
69348
+ 'sdd-draft-case-budget-invalid': Object.freeze([]),
69349
+ 'sdd-draft-requirement-mapping-invalid': Object.freeze([]),
69350
+ 'sdd-draft-repository-path-invalid': Object.freeze([]),
68996
69351
  'workspace-changes-rejected': Object.freeze([]),
68997
69352
  });
68998
69353
  function normalizeApplicationErrorRecovery(recovery) {
@@ -69008,6 +69363,13 @@ function normalizeApplicationErrorRecovery(recovery) {
69008
69363
  || actualKeys.some((key, index) => key !== expectedKeys[index])) {
69009
69364
  throw new TypeError(`Application error recovery variables are invalid for ${recovery.id}.`);
69010
69365
  }
69366
+ if (recovery.id.startsWith('stored-configuration-')
69367
+ && (![variables.issueNumber, variables.expectedVersion].every(value => typeof value === 'number' && Number.isSafeInteger(value) && value > 0)
69368
+ || (recovery.id === 'stored-configuration-schema-unsupported'
69369
+ && !(typeof variables.actualVersion === 'number'
69370
+ && Number.isSafeInteger(variables.actualVersion) && variables.actualVersion >= 0)))) {
69371
+ throw new TypeError('Stored configuration diagnostic is invalid.');
69372
+ }
69011
69373
  if (recovery.id === 'managed-branch-enrichment-failed'
69012
69374
  && (typeof variables.branchName !== 'string'
69013
69375
  || !/^[A-Za-z0-9][A-Za-z0-9._/-]{0,254}$/u.test(variables.branchName))) {
@@ -69389,6 +69751,7 @@ class Execution {
69389
69751
  this.currentIssueWorkflowAdmission = components.issueWorkflowAdmission;
69390
69752
  this.currentConfiguration.issueWorkflowProfileDigest = components.issueWorkflowProfileDigest;
69391
69753
  this.preBranchSdd = components.preBranchSdd ?? false;
69754
+ this.verificationSetup = components.verificationSetup ?? false;
69392
69755
  }
69393
69756
  }
69394
69757
  exports.Execution = Execution;
@@ -74451,6 +74814,7 @@ function combineOrganizationAccess(secrets, variables) {
74451
74814
 
74452
74815
  Object.defineProperty(exports, "__esModule", ({ value: true }));
74453
74816
  exports.isGithubAlreadyExists = exports.isGithubPermissionDenied = exports.isGithubRateLimited = exports.isGithubNotFound = exports.getGithubErrorStatus = void 0;
74817
+ exports.githubReadErrorCode = githubReadErrorCode;
74454
74818
  const getGithubErrorStatus = (error) => {
74455
74819
  if (typeof error !== "object" || error === null)
74456
74820
  return undefined;
@@ -74460,6 +74824,23 @@ const getGithubErrorStatus = (error) => {
74460
74824
  exports.getGithubErrorStatus = getGithubErrorStatus;
74461
74825
  const isGithubNotFound = (error) => (0, exports.getGithubErrorStatus)(error) === 404;
74462
74826
  exports.isGithubNotFound = isGithubNotFound;
74827
+ /** Maps failed metadata reads without copying untrusted provider text. */
74828
+ function githubReadErrorCode(error) {
74829
+ const status = (0, exports.getGithubErrorStatus)(error);
74830
+ if (status === 401)
74831
+ return 'authorization.credential-invalid';
74832
+ if ((0, exports.isGithubRateLimited)(error))
74833
+ return 'provider.rate-limited';
74834
+ if (status === 403)
74835
+ return 'authorization.denied';
74836
+ if (status === 404)
74837
+ return 'provider.not-found';
74838
+ if (status === 409 || status === 412)
74839
+ return 'provider.conflict';
74840
+ if (status === 400 || status === 422)
74841
+ return 'provider.contract-invalid';
74842
+ return 'provider.unavailable';
74843
+ }
74463
74844
  const isGithubRateLimited = (error) => {
74464
74845
  const status = (0, exports.getGithubErrorStatus)(error);
74465
74846
  if (status === 429)
@@ -75170,8 +75551,9 @@ class IssueContentRepository {
75170
75551
  return issue.body ?? '';
75171
75552
  }
75172
75553
  catch (error) {
75173
- (0, logger_1.logError)((0, application_error_1.toApplicationError)(error, 'provider.unavailable', `Unable to read issue #${issueNumber} description.`));
75174
- throw error;
75554
+ const semanticError = (0, application_error_1.toApplicationError)(error, (0, github_error_policy_1.githubReadErrorCode)(error), 'Unable to read the issue or pull-request description.');
75555
+ (0, logger_1.logError)(semanticError);
75556
+ throw semanticError;
75175
75557
  }
75176
75558
  };
75177
75559
  this.getIssueDescription = async (owner, repository, issueNumber, token) => {
@@ -77176,12 +77558,13 @@ class PullRequestApprovalRepository {
77176
77558
  collectDiagnostic(diagnostics, cause);
77177
77559
  }
77178
77560
  }
77561
+ const checkClient = this.checkOctokit ?? this.octokit;
77179
77562
  const [files, reviews, comments, headChecks, mergeChecks, headRuns, mergeRuns, rules, user] = await Promise.all([
77180
77563
  this.allPages('files', this.octokit.rest.pulls.listFiles, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
77181
77564
  this.allPages('reviews', this.octokit.rest.pulls.listReviews, { owner: target.owner, repo: target.repository, pull_number: target.pullNumber }),
77182
77565
  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([]),
77566
+ this.allPages('head-checks', checkClient.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: headSha, filter: 'all' }, checkClient),
77567
+ testedMergeSha ? this.allPages('merge-checks', checkClient.rest.checks.listForRef, { owner: target.owner, repo: target.repository, ref: testedMergeSha, filter: 'all' }, checkClient) : Promise.resolve([]),
77185
77568
  this.allPages('head-runs', this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: headSha }),
77186
77569
  testedMergeSha ? this.allPages('merge-runs', this.octokit.rest.actions.listWorkflowRunsForRepo, { owner: target.owner, repo: target.repository, head_sha: testedMergeSha }) : Promise.resolve([]),
77187
77570
  this.effectiveRules(target.owner, target.repository, pull.base.ref, diagnostics),
@@ -77439,10 +77822,10 @@ class PullRequestApprovalRepository {
77439
77822
  return { readable: false, dismissesStaleReviews: false, requiredChecks: [] };
77440
77823
  }
77441
77824
  }
77442
- async allPages(operation, method, params) {
77825
+ async allPages(operation, method, params, client = this.octokit) {
77443
77826
  return (0, approval_evidence_read_1.readApprovalEvidence)(operation, async () => {
77444
77827
  const result = [];
77445
- for await (const response of this.octokit.paginate.iterator(method, { ...params, per_page: 100 })) {
77828
+ for await (const response of client.paginate.iterator(method, { ...params, per_page: 100 })) {
77446
77829
  const page = Array.isArray(response.data) ? response.data
77447
77830
  : record(response.data)?.check_runs ?? record(response.data)?.workflow_runs
77448
77831
  ?? record(response.data)?.artifacts ?? record(response.data)?.jobs;
@@ -77533,8 +77916,8 @@ function collectDiagnostic(diagnostics, cause) {
77533
77916
 
77534
77917
  Object.defineProperty(exports, "__esModule", ({ value: true }));
77535
77918
  exports.PullRequestChangesRepository = void 0;
77919
+ const pull_request_review_error_metadata_1 = __nccwpck_require__(54354);
77536
77920
  const logger_1 = __nccwpck_require__(91151);
77537
- const pull_request_review_errors_1 = __nccwpck_require__(46445);
77538
77921
  const github_pagination_policy_1 = __nccwpck_require__(44812);
77539
77922
  const application_error_1 = __nccwpck_require__(75999);
77540
77923
  class PullRequestChangesRepository {
@@ -77547,7 +77930,7 @@ class PullRequestChangesRepository {
77547
77930
  }
77548
77931
  catch (error) {
77549
77932
  (0, logger_1.logError)((0, application_error_1.toApplicationError)(error, 'provider.unavailable', 'Unable to read the pull request review diff.'));
77550
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'list-files');
77933
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'list-files');
77551
77934
  }
77552
77935
  };
77553
77936
  this.getBoundedBugbotReviewDiffSnapshot = async (owner, repository, pullNumber, token) => {
@@ -77589,7 +77972,7 @@ class PullRequestChangesRepository {
77589
77972
  }
77590
77973
  catch (error) {
77591
77974
  (0, logger_1.logError)((0, application_error_1.toApplicationError)(error, 'provider.unavailable', 'Unable to read the pull request review diff.'));
77592
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'list-files');
77975
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'list-files');
77593
77976
  }
77594
77977
  };
77595
77978
  /** Head commit SHA of the PR (for creating review). */
@@ -77608,7 +77991,7 @@ class PullRequestChangesRepository {
77608
77991
  }
77609
77992
  catch (error) {
77610
77993
  (0, logger_1.logError)((0, application_error_1.toApplicationError)(error, 'provider.unavailable', 'Unable to read the pull request head SHA.'));
77611
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "get-head-sha");
77994
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "get-head-sha");
77612
77995
  }
77613
77996
  };
77614
77997
  }
@@ -77951,6 +78334,7 @@ function toBugbotPullRequestIdentity(value) {
77951
78334
 
77952
78335
  Object.defineProperty(exports, "__esModule", ({ value: true }));
77953
78336
  exports.PullRequestReviewCommentCommandRepository = void 0;
78337
+ const pull_request_review_error_metadata_1 = __nccwpck_require__(54354);
77954
78338
  const pull_request_review_errors_1 = __nccwpck_require__(46445);
77955
78339
  const github_pagination_policy_1 = __nccwpck_require__(44812);
77956
78340
  class PullRequestReviewCommentCommandRepository {
@@ -78019,7 +78403,7 @@ class PullRequestReviewCommentCommandRepository {
78019
78403
  const context = comments.length > 0
78020
78404
  ? { failedCount: comments.length, totalCount: comments.length }
78021
78405
  : undefined;
78022
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "publish-comments", context);
78406
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "publish-comments", context);
78023
78407
  }
78024
78408
  }
78025
78409
  async updatePullRequestReview(owner, repository, pullRequestNumber, reviewIdentity, body, token) {
@@ -78040,7 +78424,7 @@ class PullRequestReviewCommentCommandRepository {
78040
78424
  throw new pull_request_review_errors_1.PullRequestReviewOperationError('update-review');
78041
78425
  }
78042
78426
  catch (error) {
78043
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'update-review');
78427
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'update-review');
78044
78428
  }
78045
78429
  }
78046
78430
  async updatePullRequestReviewComment(_owner, _repository, commentIdentity, body, token) {
@@ -78059,7 +78443,7 @@ class PullRequestReviewCommentCommandRepository {
78059
78443
  }
78060
78444
  }
78061
78445
  catch (error) {
78062
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "update-comment");
78446
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "update-comment");
78063
78447
  }
78064
78448
  }
78065
78449
  }
@@ -78075,7 +78459,7 @@ exports.PullRequestReviewCommentCommandRepository = PullRequestReviewCommentComm
78075
78459
 
78076
78460
  Object.defineProperty(exports, "__esModule", ({ value: true }));
78077
78461
  exports.PullRequestReviewCommentQueryRepository = void 0;
78078
- const pull_request_review_errors_1 = __nccwpck_require__(46445);
78462
+ const pull_request_review_error_metadata_1 = __nccwpck_require__(54354);
78079
78463
  const github_pagination_policy_1 = __nccwpck_require__(44812);
78080
78464
  function toReviewComment(comment) {
78081
78465
  if (typeof comment.node_id !== "string" || comment.node_id.length === 0) {
@@ -78131,7 +78515,7 @@ class PullRequestReviewCommentQueryRepository {
78131
78515
  return comments;
78132
78516
  }
78133
78517
  catch (error) {
78134
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "list-comments");
78518
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "list-comments");
78135
78519
  }
78136
78520
  }
78137
78521
  async listBugbotPullRequestReviewCommentsBounded(owner, repository, pullRequestNumber, token) {
@@ -78174,7 +78558,7 @@ class PullRequestReviewCommentQueryRepository {
78174
78558
  };
78175
78559
  }
78176
78560
  catch (error) {
78177
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "list-comments");
78561
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "list-comments");
78178
78562
  }
78179
78563
  }
78180
78564
  async listPullRequestReviews(owner, repository, pullRequestNumber, token) {
@@ -78188,7 +78572,7 @@ class PullRequestReviewCommentQueryRepository {
78188
78572
  return reviews;
78189
78573
  }
78190
78574
  catch (error) {
78191
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'list-reviews');
78575
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'list-reviews');
78192
78576
  }
78193
78577
  }
78194
78578
  async getPullRequestReviewCommentBody(owner, repository, _pullRequestNumber, commentId, token) {
@@ -78202,13 +78586,37 @@ class PullRequestReviewCommentQueryRepository {
78202
78586
  return data.body ?? null;
78203
78587
  }
78204
78588
  catch (error) {
78205
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "get-comment");
78589
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "get-comment");
78206
78590
  }
78207
78591
  }
78208
78592
  }
78209
78593
  exports.PullRequestReviewCommentQueryRepository = PullRequestReviewCommentQueryRepository;
78210
78594
 
78211
78595
 
78596
+ /***/ }),
78597
+
78598
+ /***/ 54354:
78599
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
78600
+
78601
+ "use strict";
78602
+
78603
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
78604
+ exports.toPullRequestReviewOperationError = toPullRequestReviewOperationError;
78605
+ const pull_request_review_errors_1 = __nccwpck_require__(46445);
78606
+ /** Only safe HTTP metadata crosses the provider boundary; provider prose never does. */
78607
+ function toPullRequestReviewOperationError(error, operation, context) {
78608
+ if (!error || typeof error !== 'object')
78609
+ return (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, operation, context);
78610
+ const record = error;
78611
+ return (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, operation, {
78612
+ ...context,
78613
+ ...(typeof record.status === 'number' ? { providerStatus: record.status } : {}),
78614
+ ...(typeof record.response?.headers?.['x-github-request-id'] === 'string'
78615
+ ? { providerReference: record.response.headers['x-github-request-id'] } : {}),
78616
+ });
78617
+ }
78618
+
78619
+
78212
78620
  /***/ }),
78213
78621
 
78214
78622
  /***/ 2307:
@@ -78319,6 +78727,7 @@ function nextConnectionCursor(pageInfo, seenCursors) {
78319
78727
 
78320
78728
  Object.defineProperty(exports, "__esModule", ({ value: true }));
78321
78729
  exports.PullRequestReviewThreadRepository = void 0;
78730
+ const pull_request_review_error_metadata_1 = __nccwpck_require__(54354);
78322
78731
  const logger_1 = __nccwpck_require__(91151);
78323
78732
  const pull_request_review_errors_1 = __nccwpck_require__(46445);
78324
78733
  const pull_request_review_thread_locator_1 = __nccwpck_require__(2307);
@@ -78366,7 +78775,7 @@ class PullRequestReviewThreadRepository {
78366
78775
  return states;
78367
78776
  }
78368
78777
  catch (error) {
78369
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'list-threads');
78778
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'list-threads');
78370
78779
  }
78371
78780
  };
78372
78781
  this.listBugbotPullRequestReviewThreadStatesBounded = async (owner, repository, pullNumber, token) => {
@@ -78435,7 +78844,7 @@ class PullRequestReviewThreadRepository {
78435
78844
  };
78436
78845
  }
78437
78846
  catch (error) {
78438
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'list-threads');
78847
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'list-threads');
78439
78848
  }
78440
78849
  };
78441
78850
  this.resolvePullRequestReviewThread = async (owner, repository, pullNumber, commentIdentity, token) => {
@@ -78459,7 +78868,7 @@ class PullRequestReviewThreadRepository {
78459
78868
  (0, logger_1.logDebugInfo)('Resolved pull request review thread.');
78460
78869
  }
78461
78870
  catch (error) {
78462
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'resolve-thread');
78871
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'resolve-thread');
78463
78872
  }
78464
78873
  };
78465
78874
  this.unresolvePullRequestReviewThread = async (owner, repository, pullNumber, commentIdentity, token) => {
@@ -78483,7 +78892,7 @@ class PullRequestReviewThreadRepository {
78483
78892
  (0, logger_1.logDebugInfo)('Reopened pull request review thread.');
78484
78893
  }
78485
78894
  catch (error) {
78486
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, 'unresolve-thread');
78895
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, 'unresolve-thread');
78487
78896
  }
78488
78897
  };
78489
78898
  }
@@ -78500,7 +78909,7 @@ exports.PullRequestReviewThreadRepository = PullRequestReviewThreadRepository;
78500
78909
 
78501
78910
  Object.defineProperty(exports, "__esModule", ({ value: true }));
78502
78911
  exports.PullRequestReviewerRepository = void 0;
78503
- const pull_request_review_errors_1 = __nccwpck_require__(46445);
78912
+ const pull_request_review_error_metadata_1 = __nccwpck_require__(54354);
78504
78913
  const github_pagination_policy_1 = __nccwpck_require__(44812);
78505
78914
  const COMPLETED_REVIEW_STATES = new Set([
78506
78915
  "APPROVED",
@@ -78533,7 +78942,7 @@ class PullRequestReviewerRepository {
78533
78942
  return [...reviewers.values()];
78534
78943
  }
78535
78944
  catch (error) {
78536
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "list-reviewers");
78945
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "list-reviewers");
78537
78946
  }
78538
78947
  }
78539
78948
  async addReviewersToPullRequest(owner, repository, pullRequestNumber, reviewers, token) {
@@ -78558,7 +78967,7 @@ class PullRequestReviewerRepository {
78558
78967
  return [...confirmed.values()];
78559
78968
  }
78560
78969
  catch (error) {
78561
- throw (0, pull_request_review_errors_1.toPullRequestReviewOperationError)(error, "request-reviewers");
78970
+ throw (0, pull_request_review_error_metadata_1.toPullRequestReviewOperationError)(error, "request-reviewers");
78562
78971
  }
78563
78972
  }
78564
78973
  async listRequestedReviewers(client, parameters) {
@@ -79976,10 +80385,15 @@ function matchesConstrainedHead(target, candidate) {
79976
80385
  /***/ }),
79977
80386
 
79978
80387
  /***/ 31011:
79979
- /***/ ((__unused_webpack_module, exports) => {
80388
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
79980
80389
 
79981
80390
  "use strict";
79982
80391
 
80392
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
80393
+ exports.isExistingFindingFullyResolved = isExistingFindingFullyResolved;
80394
+ exports.findExistingFindingInfo = findExistingFindingInfo;
80395
+ exports.findExistingFindingMatch = findExistingFindingMatch;
80396
+ exports.retainExistingFindingIds = retainExistingFindingIds;
79983
80397
  /**
79984
80398
  * Provider-neutral Bugbot finding and durable identity contracts.
79985
80399
  *
@@ -79987,9 +80401,7 @@ function matchesConstrainedHead(target, candidate) {
79987
80401
  * them in the domain prevents policies from depending on a particular use-case
79988
80402
  * folder and gives every adapter one stable semantic vocabulary.
79989
80403
  */
79990
- Object.defineProperty(exports, "__esModule", ({ value: true }));
79991
- exports.isExistingFindingFullyResolved = isExistingFindingFullyResolved;
79992
- exports.findExistingFindingInfo = findExistingFindingInfo;
80404
+ const finding_identity_1 = __nccwpck_require__(91853);
79993
80405
  function isExistingFindingFullyResolved(finding) {
79994
80406
  const destinations = [finding.issue, finding.pullRequest].filter((destination) => destination != null);
79995
80407
  return (destinations.length > 0 &&
@@ -79997,21 +80409,62 @@ function isExistingFindingFullyResolved(finding) {
79997
80409
  finding.pullRequest?.verificationRequired !== true);
79998
80410
  }
79999
80411
  function findExistingFindingInfo(existingByFindingId, finding) {
80412
+ return findExistingFindingMatch(existingByFindingId, finding)?.info;
80413
+ }
80414
+ /** A match carries its durable key so updating a comment cannot re-key it. */
80415
+ function findExistingFindingMatch(existingByFindingId, finding) {
80000
80416
  const direct = existingByFindingId[finding.id];
80001
80417
  if (direct && identitiesAreCompatible(direct, finding))
80002
- return direct;
80003
- const candidates = Object.values(existingByFindingId);
80418
+ return { id: finding.id, info: direct };
80419
+ const candidates = Object.entries(existingByFindingId);
80004
80420
  if (finding.fingerprint) {
80005
- const locationMatch = candidates.find((candidate) => candidate.issue?.fingerprint === finding.fingerprint
80421
+ const locationMatches = candidates.filter(([, candidate]) => candidate.issue?.fingerprint === finding.fingerprint
80006
80422
  || candidate.pullRequest?.fingerprint === finding.fingerprint);
80007
- if (locationMatch)
80008
- return locationMatch;
80423
+ if (locationMatches.length > 0)
80424
+ return uniqueFindingMatch(locationMatches);
80009
80425
  }
80010
80426
  if (!finding.semanticFingerprint)
80011
80427
  return undefined;
80012
- const semanticMatches = candidates.filter((candidate) => candidate.issue?.semanticFingerprint === finding.semanticFingerprint
80428
+ const semanticMatches = candidates.filter(([, candidate]) => candidate.issue?.semanticFingerprint === finding.semanticFingerprint
80013
80429
  || candidate.pullRequest?.semanticFingerprint === finding.semanticFingerprint);
80014
- return semanticMatches.length === 1 ? semanticMatches[0] : undefined;
80430
+ return uniqueFindingMatch(semanticMatches);
80431
+ }
80432
+ /**
80433
+ * Preserve trusted IDs across title/location changes, before limits, publication
80434
+ * and final projection. Multiple reports of one uniquely matched durable finding
80435
+ * share one record; unmatched or ambiguous reports remain independent evidence.
80436
+ */
80437
+ function retainExistingFindingIds(findings, existingByFindingId) {
80438
+ const retained = new Set();
80439
+ const durableIds = new Set(Object.keys(existingByFindingId));
80440
+ // Reserve the whole input up front so a generated ID cannot take another
80441
+ // report's ID, including one that occurs later in the response.
80442
+ const reservedIds = new Set([...durableIds, ...findings.map((finding) => finding.id)]);
80443
+ const emittedIds = new Set();
80444
+ return findings.flatMap((finding) => {
80445
+ const match = findExistingFindingMatch(existingByFindingId, finding);
80446
+ if (!match) {
80447
+ let id = finding.id;
80448
+ if (durableIds.has(id) || emittedIds.has(id)) {
80449
+ const base = `candidate-${(0, finding_identity_1.buildFindingFingerprint)(finding)}`;
80450
+ id = base;
80451
+ let suffix = 0;
80452
+ while (reservedIds.has(id))
80453
+ id = `${base}-${++suffix}`;
80454
+ reservedIds.add(id);
80455
+ }
80456
+ emittedIds.add(id);
80457
+ return [id === finding.id ? finding : { ...finding, id }];
80458
+ }
80459
+ if (retained.has(match.id))
80460
+ return [];
80461
+ retained.add(match.id);
80462
+ emittedIds.add(match.id);
80463
+ return [finding.id === match.id ? finding : { ...finding, id: match.id }];
80464
+ });
80465
+ }
80466
+ function uniqueFindingMatch(matches) {
80467
+ return matches.length === 1 ? { id: matches[0][0], info: matches[0][1] } : undefined;
80015
80468
  }
80016
80469
  function identitiesAreCompatible(existing, finding) {
80017
80470
  const existingFingerprints = [
@@ -80553,6 +81006,63 @@ function isCopilotCommentRequest(commentBody, botLogin) {
80553
81006
  }
80554
81007
 
80555
81008
 
81009
+ /***/ }),
81010
+
81011
+ /***/ 33430:
81012
+ /***/ ((__unused_webpack_module, exports) => {
81013
+
81014
+ "use strict";
81015
+
81016
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
81017
+ exports.COPILOT_COMMENT_REMOTE_WORKFLOW = exports.COPILOT_COMMENT_SELF_WORKFLOW = exports.COPILOT_COMMENT_RUNTIME = void 0;
81018
+ exports.isCopilotCommentWorkflow = isCopilotCommentWorkflow;
81019
+ exports.isCopilotCommentRunner = isCopilotCommentRunner;
81020
+ exports.copilotCommentRunner = copilotCommentRunner;
81021
+ /** The comment coordinator is a versioned Copilot workflow, not an arbitrary reusable job. */
81022
+ exports.COPILOT_COMMENT_RUNTIME = 'copilot_comment_runtime.yml';
81023
+ exports.COPILOT_COMMENT_SELF_WORKFLOW = `$/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}`;
81024
+ exports.COPILOT_COMMENT_REMOTE_WORKFLOW = `vypdev/copilot/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}@v3`;
81025
+ function isCopilotCommentWorkflow(value) {
81026
+ return typeof value === 'string' && (value === exports.COPILOT_COMMENT_SELF_WORKFLOW
81027
+ || /^vypdev\/copilot\/\.github\/workflows\/copilot_comment_runtime\.yml@(?:v3(?:\.[0-9]+\.[0-9]+)?|[a-f0-9]{40})$/u.test(value));
81028
+ }
81029
+ const literal = (value) => typeof value === 'string' && value.length > 0 && value.length <= 100
81030
+ && value === value.trim() && !/[\p{Cc}\p{Cf}${}<>]/u.test(value);
81031
+ const labels = (value) => literal(value) || Array.isArray(value) && value.length > 0 && value.length <= 10
81032
+ && value.every(literal) && new Set(value.map(label => label.toLowerCase())).size === value.length;
81033
+ /** Runner routing is literal data; expressions need their original full workflow reviewed. */
81034
+ function isCopilotCommentRunner(value) {
81035
+ if (labels(value))
81036
+ return true;
81037
+ if (!value || typeof value !== 'object' || Array.isArray(value))
81038
+ return false;
81039
+ const route = value;
81040
+ const keys = Object.keys(route);
81041
+ return keys.length > 0 && (route.group !== undefined || route.labels !== undefined)
81042
+ && keys.every(key => key === 'group' || key === 'labels')
81043
+ && (route.group === undefined || literal(route.group))
81044
+ && (route.labels === undefined || labels(route.labels));
81045
+ }
81046
+ function copilotCommentRunner(job) {
81047
+ if (!job || !isCopilotCommentWorkflow(job.uses))
81048
+ return job?.['runs-on'];
81049
+ const inputs = job.with;
81050
+ if (typeof inputs?.['runs-on'] !== 'string')
81051
+ throw new Error('Comment workflow runner JSON is unavailable; review the workflow separately.');
81052
+ try {
81053
+ if (inputs['runs-on'].length > 16000)
81054
+ throw new Error('Runner JSON exceeds its bound.');
81055
+ const route = JSON.parse(inputs['runs-on']);
81056
+ if (!isCopilotCommentRunner(route))
81057
+ throw new Error('Unsupported execution route.');
81058
+ return route;
81059
+ }
81060
+ catch {
81061
+ throw new Error('Comment workflow runner JSON is invalid; review the workflow separately.');
81062
+ }
81063
+ }
81064
+
81065
+
80556
81066
  /***/ }),
80557
81067
 
80558
81068
  /***/ 72418:
@@ -82357,7 +82867,7 @@ function parsePositiveSafeInteger(value) {
82357
82867
  "use strict";
82358
82868
 
82359
82869
  Object.defineProperty(exports, "__esModule", ({ value: true }));
82360
- exports.SDD_REQUIRED_HEADINGS = exports.SddOwnerFormatFailure = exports.SddDraftFormatFailure = exports.SDD_MAX_UPDATE_CHARACTERS = exports.SDD_MAX_DRAFT_CHARACTERS = exports.SDD_MIN_DRAFT_CHARACTERS = exports.SDD_GATE_MARKER = void 0;
82870
+ exports.SDD_REQUIRED_HEADINGS = exports.SddOwnerFormatFailure = exports.SddDraftFormatFailure = exports.SddOwnershipFailure = exports.SDD_MAX_UPDATE_CHARACTERS = exports.SDD_MAX_DRAFT_CHARACTERS = exports.SDD_MIN_DRAFT_CHARACTERS = exports.SDD_GATE_MARKER = void 0;
82361
82871
  exports.retainSddAnswers = retainSddAnswers;
82362
82872
  exports.normalizeSddIssueTitle = normalizeSddIssueTitle;
82363
82873
  exports.isSafeSddPath = isSafeSddPath;
@@ -82368,6 +82878,7 @@ exports.isSddAnswerComment = isSddAnswerComment;
82368
82878
  exports.parseSddAnswer = parseSddAnswer;
82369
82879
  exports.validateSddMarkdown = validateSddMarkdown;
82370
82880
  exports.composeSddUpdate = composeSddUpdate;
82881
+ exports.recoverSddUpdate = recoverSddUpdate;
82371
82882
  exports.SDD_GATE_MARKER = 'copilot:sdd-gate:v1';
82372
82883
  exports.SDD_MIN_DRAFT_CHARACTERS = 1800;
82373
82884
  exports.SDD_MAX_DRAFT_CHARACTERS = 70000;
@@ -82395,6 +82906,15 @@ function normalizeSddIssueTitle(title) {
82395
82906
  function isSafeSddPath(path) {
82396
82907
  return SDD_PATH.test(path) && !['specs/CATALOG.md', 'specs/_template.md'].includes(path);
82397
82908
  }
82909
+ /** Closed diagnostics contain no model-selected identifiers or provider text. */
82910
+ class SddOwnershipFailure extends Error {
82911
+ constructor(reason) {
82912
+ super(`SDD ownership analysis rejected (${reason}).`);
82913
+ this.reason = reason;
82914
+ this.name = 'SddOwnershipFailure';
82915
+ }
82916
+ }
82917
+ exports.SddOwnershipFailure = SddOwnershipFailure;
82398
82918
  /** The agent may propose ownership but cannot invent a catalogued owner or arbitrary path. */
82399
82919
  function parseSddPlan(value, catalog) {
82400
82920
  if (!isRecord(value))
@@ -82412,14 +82932,16 @@ function parseSddPlan(value, catalog) {
82412
82932
  const ownerPaths = catalog.get(capabilityId);
82413
82933
  const registered = [...catalog.values()].some(paths => paths.includes(path));
82414
82934
  if (action === 'update' && (!ownerPaths?.includes(path) || !registered)) {
82415
- throw new Error('The requested SDD update is not owned by the selected catalog capability.');
82416
- }
82417
- if (action === 'companion' && (!ownerPaths || registered)) {
82418
- throw new Error('A companion SDD requires an existing owner and a new path.');
82419
- }
82420
- if (action === 'new' && (ownerPaths || registered)) {
82421
- throw new Error('A new SDD requires an unregistered capability and path.');
82422
- }
82935
+ throw new SddOwnershipFailure('update-owner-mismatch');
82936
+ }
82937
+ if (action === 'companion' && !ownerPaths)
82938
+ throw new SddOwnershipFailure('companion-owner-unknown');
82939
+ if (action === 'companion' && registered)
82940
+ throw new SddOwnershipFailure('companion-path-registered');
82941
+ if (action === 'new' && ownerPaths)
82942
+ throw new SddOwnershipFailure('new-owner-registered');
82943
+ if (action === 'new' && registered)
82944
+ throw new SddOwnershipFailure('new-path-registered');
82423
82945
  if (!Array.isArray(value.questions) || value.questions.length > 8) {
82424
82946
  throw new Error('The SDD analysis must contain at most eight blocking questions.');
82425
82947
  }
@@ -82660,8 +83182,24 @@ function composeSddUpdate(existing, change) {
82660
83182
  validateSddMarkdown(change);
82661
83183
  if (change.length > exports.SDD_MAX_UPDATE_CHARACTERS)
82662
83184
  throw new Error('An SDD update appendix exceeds 18000 characters; use a proportional change or a companion SDD.');
83185
+ const appendix = shiftSddHeadings(change, 1);
83186
+ const merged = `${existing.trimEnd()}\n\n${appendix.trim()}\n`;
83187
+ validateSddMarkdown(merged);
83188
+ return merged;
83189
+ }
83190
+ /** Recovery validates the original candidate, not a second copy of its retained baseline. */
83191
+ function recoverSddUpdate(existing, published) {
83192
+ const prefix = `${existing.trimEnd()}\n\n`;
83193
+ if (!published.startsWith(prefix))
83194
+ return undefined;
83195
+ // Composition normalizes outer whitespace and adds a publication newline.
83196
+ // Reconstruct an equivalent candidate inside the original size bounds.
83197
+ const change = shiftSddHeadings(published.slice(prefix.length), -1).trim().padEnd(exports.SDD_MIN_DRAFT_CHARACTERS, '\n');
83198
+ return composeSddUpdate(existing, change) === published ? change : undefined;
83199
+ }
83200
+ function shiftSddHeadings(source, direction) {
82663
83201
  let fence;
82664
- const appendix = change.split('\n').map(line => {
83202
+ return source.split('\n').map(line => {
82665
83203
  const boundary = line.match(/^\s*(`{3,}|~{3,})/);
82666
83204
  if (boundary) {
82667
83205
  if (!fence)
@@ -82670,11 +83208,11 @@ function composeSddUpdate(existing, change) {
82670
83208
  fence = undefined;
82671
83209
  return line;
82672
83210
  }
82673
- return !fence && /^#{1,5} /.test(line) ? `#${line}` : line;
83211
+ if (fence)
83212
+ return line;
83213
+ return direction === 1 ? (/^#{1,5} /.test(line) ? `#${line}` : line)
83214
+ : (/^#{2,6} /.test(line) ? line.slice(1) : line);
82674
83215
  }).join('\n');
82675
- const merged = `${existing.trimEnd()}\n\n${appendix.trim()}\n`;
82676
- validateSddMarkdown(merged);
82677
- return merged;
82678
83216
  }
82679
83217
  function serializeSddGateValue(value) {
82680
83218
  // Human answer text must never terminate its hidden state comment.
@@ -83271,6 +83809,254 @@ function replyRequestBodyDigest(body) {
83271
83809
  }
83272
83810
 
83273
83811
 
83812
+ /***/ }),
83813
+
83814
+ /***/ 27910:
83815
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
83816
+
83817
+ "use strict";
83818
+
83819
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
83820
+ exports.SDD_CONSISTENCY_PROMPT = void 0;
83821
+ exports.reservedSddCaseIds = reservedSddCaseIds;
83822
+ exports.validateSddDraftConsistency = validateSddDraftConsistency;
83823
+ const pre_branch_sdd_1 = __nccwpck_require__(34730);
83824
+ const CASE = /\b(?:[A-Za-z][A-Za-z0-9]*-)+C\d+\b/gu;
83825
+ const CASE_ID = /^(?:[A-Za-z][A-Za-z0-9]*-)+C\d+$/u;
83826
+ const REQUIREMENT_ID = /^[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)+$/u;
83827
+ /** Generated candidates use visible tables; retained legacy owners are never reformatted. */
83828
+ exports.SDD_CONSISTENCY_PROMPT = `Consistency contract for the proposed draft/appendix (not the retained owner):
83829
+ In section 4 include one table: Requirement | Behavior. Give every goal a stable requirement ID.
83830
+ In section 14 include one budget table: Area | Minimum distinct cases | Behaviors/risks covered; positive integers and one Total.
83831
+ Also in section 14 include one inventory table: Case ID | Area | Requirements | Scenario.
83832
+ Each row is one distinct executable case with a fully qualified ID such as capability-change-C01, one exact budget area, comma-separated requirement IDs and an observable scenario. Never use shorthand C01, ranges or redefine an ID found in any owning SDD. Reference retained baseline cases in prose using their full IDs; count only the new inventory.
83833
+ In section 17 include one table: Requirement | Cases. List comma-separated full case IDs for every requirement. Its links must exactly match the case inventory in both directions, with no undefined or generic documentation checks.
83834
+ In section 15 include one table: Path | Change. Change is update, reference or create. Include the selected SDD path itself with update for an existing SDD or create for a new/companion SDD. Use existing immutable-base files for update/reference. Only explicitly proposed new files may use create; never mark a missing current document as an existing artifact. Cite repository files as full repository-relative paths in backticks, or relative Markdown file links. Put every planned new file in this table. These tables are publication consistency checks, not runtime/security acceptance.`;
83835
+ function fail(reason) {
83836
+ // Closed diagnostics: rejected Markdown and repository text never become repair instructions.
83837
+ throw new pre_branch_sdd_1.SddDraftFormatFailure(reason, `The SDD draft violates its ${reason} consistency contract.`);
83838
+ }
83839
+ /** Excludes examples and hidden records from the contract. */
83840
+ function visible(source) {
83841
+ let fence;
83842
+ let comment = false;
83843
+ return source.replace(/\r\n/gu, '\n').split('\n').map(line => {
83844
+ const boundary = /^\s*(`{3,}|~{3,})/u.exec(line);
83845
+ if (fence) {
83846
+ // Comment syntax inside code is literal; only the original line can close it.
83847
+ if (boundary && boundary[1][0] === fence[0] && boundary[1].length >= fence.length
83848
+ && /^ {0,3}(?:`+|~+)[ \t]*$/u.test(line))
83849
+ fence = undefined;
83850
+ return '';
83851
+ }
83852
+ if (!comment && boundary) {
83853
+ fence = boundary[1];
83854
+ return '';
83855
+ }
83856
+ let result = '';
83857
+ let offset = 0;
83858
+ while (offset < line.length) {
83859
+ const marker = comment ? '-->' : '<!--';
83860
+ const next = line.indexOf(marker, offset);
83861
+ if (next < 0)
83862
+ return result + (comment ? '' : line.slice(offset));
83863
+ if (!comment)
83864
+ result += line.slice(offset, next) + ' ';
83865
+ offset = next + marker.length;
83866
+ comment = !comment;
83867
+ }
83868
+ return result;
83869
+ }).join('\n');
83870
+ }
83871
+ function clean(value) { return value.trim().replace(/^(?:\*\*|__|`)(.*?)(?:\*\*|__|`)$/u, '$1').trim(); }
83872
+ function table(source, section, headers, reason) {
83873
+ const sections = [...source.matchAll(/^## (\d+)\. [^\n]*$/gmu)];
83874
+ const matches = sections.filter(heading => Number(heading[1]) === section);
83875
+ if (matches.length !== 1)
83876
+ return fail(reason);
83877
+ const start = matches[0];
83878
+ const end = sections.find(heading => heading.index > start.index)?.index ?? source.length;
83879
+ const lines = source.slice(start.index + start[0].length, end).split('\n');
83880
+ const found = [];
83881
+ for (let index = 0; index < lines.length; index++) {
83882
+ if (!/^\s*\|/u.test(lines[index]))
83883
+ continue;
83884
+ const cells = (line) => line.trim().replace(/^\||\|$/gu, '').split('|').map(clean);
83885
+ const header = cells(lines[index]);
83886
+ if (!headers.every((value, position) => header[position] === value) || header.length !== headers.length)
83887
+ continue;
83888
+ const separator = cells(lines[++index] ?? '');
83889
+ if (separator.length !== headers.length || !separator.every(cell => /^:?-{3,}:?$/u.test(cell)))
83890
+ return fail(reason);
83891
+ const rows = [];
83892
+ while (++index < lines.length && /^\s*\|/u.test(lines[index])) {
83893
+ const row = cells(lines[index]);
83894
+ if (row.length !== headers.length || row.some(cell => !cell))
83895
+ return fail(reason);
83896
+ rows.push(row);
83897
+ }
83898
+ if (!rows.length)
83899
+ return fail(reason);
83900
+ found.push(rows);
83901
+ }
83902
+ return found.length === 1 ? found[0] : fail(reason);
83903
+ }
83904
+ function ids(value, pattern, reason) {
83905
+ const values = value.split(/\s*,\s*/u);
83906
+ if (!values.every(id => pattern.test(id)) || new Set(values).size !== values.length)
83907
+ return fail(reason);
83908
+ return values;
83909
+ }
83910
+ function reservedSddCaseIds(documents) {
83911
+ const reserved = new Set();
83912
+ for (const document of documents) {
83913
+ const source = visible(document.markdown);
83914
+ const qualified = source.match(CASE) ?? [];
83915
+ const namespaces = new Set(qualified.map(id => id.slice(0, id.lastIndexOf('-C') + 2)));
83916
+ for (const id of qualified)
83917
+ reserved.add(id);
83918
+ // Legacy inventories often qualify C01 and abbreviate the remaining rows.
83919
+ // Reserve every plausible namespace instead of silently assigning an alias a new meaning.
83920
+ for (const match of source.matchAll(/(?<![\w-])C(\d+)\b/gu)) {
83921
+ for (const namespace of namespaces)
83922
+ reserved.add(`${namespace}${match[1]}`);
83923
+ }
83924
+ for (const match of source.matchAll(/\bC(\d+)\s*[-–—]\s*C?(\d+)\b/gu)) {
83925
+ const start = Number(match[1]);
83926
+ const end = Number(match[2]);
83927
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || end < start || end - start > 1000) {
83928
+ throw new Error('An owning SDD case range cannot be reconciled within the fixed bound; review the baseline before retrying.');
83929
+ }
83930
+ for (let number = start; number <= end; number++) {
83931
+ for (const namespace of namespaces)
83932
+ reserved.add(`${namespace}${String(number).padStart(match[1].length, '0')}`);
83933
+ }
83934
+ }
83935
+ }
83936
+ return [...reserved].sort();
83937
+ }
83938
+ function validateSddDraftConsistency(markdown, owners, inventory, sddPath) {
83939
+ const source = visible(markdown);
83940
+ const requirements = table(source, 4, ['Requirement', 'Behavior'], 'requirement-mapping');
83941
+ const requirementIds = requirements.map(row => row[0]);
83942
+ if (new Set(requirementIds).size !== requirementIds.length || !requirementIds.every(id => REQUIREMENT_ID.test(id)))
83943
+ fail('requirement-mapping');
83944
+ const cases = table(source, 14, ['Case ID', 'Area', 'Requirements', 'Scenario'], 'case-identity');
83945
+ const caseIds = cases.map(row => row[0]);
83946
+ const reserved = new Set(reservedSddCaseIds(owners));
83947
+ if (new Set(caseIds).size !== caseIds.length || caseIds.some(id => !CASE_ID.test(id) || reserved.has(id))
83948
+ || /(?<![\w-])C\d+\b/u.test(source))
83949
+ fail('case-identity');
83950
+ // References to existing owner cases are allowed, but cannot count as newly defined cases.
83951
+ if ([...source.matchAll(CASE)].some(([id]) => !caseIds.includes(id) && !reserved.has(id)))
83952
+ fail('case-identity');
83953
+ const budget = table(source, 14, ['Area', 'Minimum distinct cases', 'Behaviors/risks covered'], 'case-budget');
83954
+ const counts = new Map();
83955
+ let total;
83956
+ for (const [area, value] of budget) {
83957
+ const count = /^[1-9]\d*$/u.test(value) ? Number(value) : NaN;
83958
+ if (!Number.isSafeInteger(count) || counts.has(area) || total !== undefined)
83959
+ fail('case-budget');
83960
+ if (area === 'Total')
83961
+ total = count;
83962
+ else
83963
+ counts.set(area, count);
83964
+ }
83965
+ if (!counts.size || total !== caseIds.length || [...counts.values()].reduce((sum, count) => sum + count, 0) !== total
83966
+ || cases.some(row => !counts.has(row[1])))
83967
+ fail('case-budget');
83968
+ for (const [area, count] of counts)
83969
+ if (cases.filter(row => row[1] === area).length !== count)
83970
+ fail('case-budget');
83971
+ const edges = new Map(requirementIds.map(id => [id, new Set()]));
83972
+ for (const [id, , links] of cases) {
83973
+ for (const requirement of ids(links, REQUIREMENT_ID, 'requirement-mapping')) {
83974
+ const linked = edges.get(requirement);
83975
+ if (!linked)
83976
+ fail('requirement-mapping');
83977
+ linked.add(id);
83978
+ }
83979
+ }
83980
+ const traceability = table(source, 17, ['Requirement', 'Cases'], 'requirement-mapping');
83981
+ const seen = new Set();
83982
+ for (const [requirement, links] of traceability) {
83983
+ const expected = edges.get(requirement);
83984
+ const actual = ids(links, CASE_ID, 'requirement-mapping');
83985
+ if (!expected || seen.has(requirement) || expected.size !== actual.length || actual.some(id => !expected.has(id)))
83986
+ fail('requirement-mapping');
83987
+ seen.add(requirement);
83988
+ }
83989
+ if (seen.size !== edges.size || [...edges.values()].some(links => links.size === 0))
83990
+ fail('requirement-mapping');
83991
+ validatePaths(source, inventory, sddPath);
83992
+ }
83993
+ function safePath(value) {
83994
+ return value.length > 0 && !/[\\:*?"<>|\p{Cc}]/u.test(value)
83995
+ && value.split('/').every(segment => segment && segment !== '.' && segment !== '..' && segment.toLowerCase() !== '.git');
83996
+ }
83997
+ function validatePaths(source, inventory, sddPath) {
83998
+ const rows = table(source, 15, ['Path', 'Change'], 'repository-path');
83999
+ const expectedChange = inventory.files.has(sddPath) ? 'update' : 'create';
84000
+ if (!rows.some(([file, change]) => file === sddPath && change === expectedChange))
84001
+ fail('repository-path');
84002
+ const proposed = new Set();
84003
+ const seen = new Set();
84004
+ for (const [file, change] of rows) {
84005
+ if (!safePath(file) || seen.has(file) || inventory.blocked.has(file))
84006
+ fail('repository-path');
84007
+ seen.add(file);
84008
+ if (change === 'create') {
84009
+ if (inventory.files.has(file) || inventory.directories.has(file))
84010
+ fail('repository-path');
84011
+ if ([...proposed].some(other => file.startsWith(`${other}/`) || other.startsWith(`${file}/`)))
84012
+ fail('repository-path');
84013
+ const segments = file.split('/');
84014
+ if (segments.some((_, index) => inventory.files.has(segments.slice(0, index + 1).join('/')) || inventory.blocked.has(segments.slice(0, index + 1).join('/'))))
84015
+ fail('repository-path');
84016
+ proposed.add(file);
84017
+ }
84018
+ else if (!['update', 'reference'].includes(change) || !inventory.files.has(file))
84019
+ fail('repository-path');
84020
+ }
84021
+ const check = (file) => {
84022
+ if (!safePath(file) || (!inventory.files.has(file) && !inventory.directories.has(file) && !proposed.has(file)))
84023
+ fail('repository-path');
84024
+ };
84025
+ // Relative Markdown file links resolve against the selected SDD, never the current checkout.
84026
+ for (const match of source.matchAll(/\]\(([^\s)]+)\)/gu)) {
84027
+ const href = match[1].split(/[?#]/u)[0];
84028
+ if (!href || /^(?:[a-z][a-z0-9+.-]*:|\/)/iu.test(href))
84029
+ continue;
84030
+ let decoded;
84031
+ try {
84032
+ decoded = decodeURIComponent(href);
84033
+ }
84034
+ catch {
84035
+ return fail('repository-path');
84036
+ }
84037
+ const parts = sddPath.split('/').slice(0, -1);
84038
+ for (const part of decoded.split('/')) {
84039
+ if (part === '..') {
84040
+ if (!parts.length)
84041
+ fail('repository-path');
84042
+ parts.pop();
84043
+ }
84044
+ else if (part !== '.')
84045
+ parts.push(part);
84046
+ }
84047
+ check(parts.join('/'));
84048
+ }
84049
+ for (const match of source.matchAll(/`([^`\n]+)`/gu)) {
84050
+ const value = match[1];
84051
+ if (value.includes('/') && !/^(?:[a-z][a-z0-9+.-]*:|\/)/iu.test(value) && !/\s/u.test(value))
84052
+ check(value.replace(/\/$/u, ''));
84053
+ }
84054
+ const prose = source.replace(/\]\([^\s)]+\)/gu, ']()').replace(/[a-z][a-z0-9+.-]*:\/\/[^\s)>]+/giu, '');
84055
+ for (const match of prose.matchAll(/(?<![\w./:-])([A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)+\.[A-Za-z0-9]+)(?![\w/-])/gu))
84056
+ check(match[1]);
84057
+ }
84058
+
84059
+
83274
84060
  /***/ }),
83275
84061
 
83276
84062
  /***/ 47122:
@@ -83454,6 +84240,20 @@ exports.DEFAULT_SETUP_RUNNERS = Object.freeze({
83454
84240
  });
83455
84241
 
83456
84242
 
84243
+ /***/ }),
84244
+
84245
+ /***/ 33156:
84246
+ /***/ ((__unused_webpack_module, exports) => {
84247
+
84248
+ "use strict";
84249
+
84250
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
84251
+ exports.SETUP_VERIFICATION_ACTION_PARENTS = exports.SETUP_VERIFICATION_ACTION_PATH = void 0;
84252
+ /** Fixed consumer-owned asset: setup may create it, never regenerate or retire it. */
84253
+ exports.SETUP_VERIFICATION_ACTION_PATH = '.github/actions/copilot-verification-setup/action.yml';
84254
+ exports.SETUP_VERIFICATION_ACTION_PARENTS = ['.github', '.github/actions', '.github/actions/copilot-verification-setup'];
84255
+
84256
+
83457
84257
  /***/ }),
83458
84258
 
83459
84259
  /***/ 24596:
@@ -86280,12 +87080,14 @@ function createDeploymentOrchestrationUseCase(issueDescriptionQueryPort, publica
86280
87080
  });
86281
87081
  }
86282
87082
  const copilot_history_port_factory_1 = __nccwpck_require__(12321);
86283
- function createIssueCommentUseCaseCompositionRoot(binding) {
87083
+ const verification_setup_snapshot_1 = __nccwpck_require__(62148);
87084
+ const verification_setup_ports_1 = __nccwpck_require__(26509);
87085
+ function createIssueCommentUseCaseCompositionRoot(binding, setup = verification_setup_ports_1.DISABLED_VERIFICATION_SETUP) {
86284
87086
  const bugbot = (0, bugbot_composition_root_1.createBugbotCompositionRoot)(binding);
86285
87087
  const findings = (0, agent_capability_composition_root_1.createFindingsQueryPort)();
86286
87088
  const language = (0, agent_capability_composition_root_1.createLanguageQueryPort)();
86287
87089
  const fixer = (0, agent_capability_composition_root_1.createFixerQueryPort)();
86288
- const gitCommit = new git_commit_adapter_1.GitCommitAdapter();
87090
+ const gitCommit = new git_commit_adapter_1.GitCommitAdapter(undefined, undefined, setup);
86289
87091
  const authenticatedUser = (0, authenticated_user_composition_root_1.createAuthenticatedUserCompositionRoot)();
86290
87092
  const bugbotGit = new bound_bugbot_git_mutation_adapter_1.BoundBugbotGitMutationAdapter(gitCommit, authenticatedUser, binding.token);
86291
87093
  const pullRequestDescription = new update_pull_request_description_use_case_1.UpdatePullRequestDescriptionUseCase((0, lifecycle_capability_port_binding_1.bindPullRequestDescription)(new pull_request_lifecycle_repository_1.PullRequestLifecycleRepository((0, github_pull_request_client_factory_1.createPullRequestLifecycleClient)()), binding, new pull_request_changes_repository_1.PullRequestChangesRepository((0, github_pull_request_client_factory_1.createPullRequestChangesClient)())), (0, shared_capability_port_binding_1.bindIssueDescriptionQuery)((0, issue_content_composition_root_1.createIssueContentCompositionRoot)(), binding), (0, shared_capability_port_binding_1.bindOrganizationMembers)((0, organization_members_composition_root_1.createOrganizationMembersCompositionRoot)(), binding), (0, agent_capability_composition_root_1.createFindingsQueryPort)());
@@ -86296,12 +87098,12 @@ function createIssueCommentUseCaseCompositionRoot(binding) {
86296
87098
  catalogResolver: new resolve_message_catalog_use_case_1.ResolveMessageCatalogUseCase(language),
86297
87099
  }), new detect_potential_problems_use_case_1.DetectPotentialProblemsUseCase(findings, bugbot.scm, bugbot.telemetry, new resolve_message_catalog_use_case_1.ResolveMessageCatalogUseCase(language)), pullRequestDescription, new remember_bugbot_rule_use_case_1.RememberBugbotRuleUseCase(bugbot.rules), branchSync, (0, issue_use_case_composition_root_1.createIssueUseCaseCompositionRoot)(binding), rememberBranchPorts(binding, bugbot.scm.context), (0, pull_request_status_composition_root_1.createPullRequestStatusReadPorts)(binding, bugbot.scm.context), (0, copilot_history_port_factory_1.createCopilotHistoryReadPort)(bugbot.scm.context, process.env.GITHUB_SERVER_URL ?? 'https://github.com'), (0, sdd_evidence_composition_root_1.createSddEvidenceQueryPort)(binding, bugbot.scm.context), (0, sdd_diff_composition_root_1.createSddDiffQueryPort)(binding, bugbot.scm.context), (0, issue_completion_composition_root_2.createNativeStatusReadPort)(binding), (0, github_runtime_doctor_composition_root_1.createGithubRuntimeDoctorPorts)(binding, bugbot.scm.context));
86298
87100
  }
86299
- function createPullRequestReviewCommentUseCaseCompositionRoot(binding) {
87101
+ function createPullRequestReviewCommentUseCaseCompositionRoot(binding, setup = verification_setup_ports_1.DISABLED_VERIFICATION_SETUP) {
86300
87102
  const bugbot = (0, bugbot_composition_root_1.createBugbotCompositionRoot)(binding);
86301
87103
  const findings = (0, agent_capability_composition_root_1.createFindingsQueryPort)();
86302
87104
  const language = (0, agent_capability_composition_root_1.createLanguageQueryPort)();
86303
87105
  const fixer = (0, agent_capability_composition_root_1.createFixerQueryPort)();
86304
- const gitCommit = new git_commit_adapter_1.GitCommitAdapter();
87106
+ const gitCommit = new git_commit_adapter_1.GitCommitAdapter(undefined, undefined, setup);
86305
87107
  const authenticatedUser = (0, authenticated_user_composition_root_1.createAuthenticatedUserCompositionRoot)();
86306
87108
  const bugbotGit = new bound_bugbot_git_mutation_adapter_1.BoundBugbotGitMutationAdapter(gitCommit, authenticatedUser, binding.token);
86307
87109
  const pullRequestDescription = new update_pull_request_description_use_case_1.UpdatePullRequestDescriptionUseCase((0, lifecycle_capability_port_binding_1.bindPullRequestDescription)(new pull_request_lifecycle_repository_1.PullRequestLifecycleRepository((0, github_pull_request_client_factory_1.createPullRequestLifecycleClient)()), binding, new pull_request_changes_repository_1.PullRequestChangesRepository((0, github_pull_request_client_factory_1.createPullRequestChangesClient)())), (0, shared_capability_port_binding_1.bindIssueDescriptionQuery)((0, issue_content_composition_root_1.createIssueContentCompositionRoot)(), binding), (0, shared_capability_port_binding_1.bindOrganizationMembers)((0, organization_members_composition_root_1.createOrganizationMembersCompositionRoot)(), binding), (0, agent_capability_composition_root_1.createFindingsQueryPort)());
@@ -86328,7 +87130,7 @@ function createMainRunRouteCompositionRoot(projectBoardCommandPort, surface, set
86328
87130
  return singleAction.invoke(execution);
86329
87131
  },
86330
87132
  "issue-comment": async (execution) => {
86331
- issueComment ?? (issueComment = createIssueCommentUseCaseCompositionRoot(bugbotBinding(execution)));
87133
+ issueComment ?? (issueComment = createIssueCommentUseCaseCompositionRoot(bugbotBinding(execution), (0, verification_setup_snapshot_1.captureVerificationSetup)(execution.verificationSetup, execution.branches.main)));
86332
87134
  return issueComment.invoke(execution);
86333
87135
  },
86334
87136
  issue: async (execution) => {
@@ -86336,7 +87138,7 @@ function createMainRunRouteCompositionRoot(projectBoardCommandPort, surface, set
86336
87138
  return issue.invoke(execution);
86337
87139
  },
86338
87140
  "pull-request-review-comment": async (execution) => {
86339
- pullRequestReviewComment ?? (pullRequestReviewComment = createPullRequestReviewCommentUseCaseCompositionRoot(bugbotBinding(execution)));
87141
+ pullRequestReviewComment ?? (pullRequestReviewComment = createPullRequestReviewCommentUseCaseCompositionRoot(bugbotBinding(execution), (0, verification_setup_snapshot_1.captureVerificationSetup)(execution.verificationSetup, execution.branches.main)));
86340
87142
  return pullRequestReviewComment.invoke(execution);
86341
87143
  },
86342
87144
  "pull-request": async (execution) => {
@@ -87273,23 +88075,28 @@ var __importStar = (this && this.__importStar) || (function () {
87273
88075
  })();
87274
88076
  Object.defineProperty(exports, "__esModule", ({ value: true }));
87275
88077
  exports.GitCommitAdapter = void 0;
88078
+ const verification_executable_1 = __nccwpck_require__(20878);
88079
+ const native_verification_profiles_1 = __nccwpck_require__(22290);
87276
88080
  const exec = __importStar(__nccwpck_require__(18538));
87277
88081
  const git_authentication_environment_1 = __nccwpck_require__(16535);
87278
88082
  const untrusted_command_environment_1 = __nccwpck_require__(2304);
87279
88083
  const git_hook_isolation_1 = __nccwpck_require__(39764);
87280
88084
  const verification_runtime_preflight_1 = __nccwpck_require__(23100);
88085
+ const verification_setup_ports_1 = __nccwpck_require__(26509);
88086
+ const verification_setup_runner_1 = __nccwpck_require__(11709);
87281
88087
  class GitCommitAdapter {
87282
88088
  constructor(executeCommand = (program, args, options) => options
87283
- ? exec.exec(program, args, {
88089
+ ? exec.exec(options.resolveFromEnvironment && options.env ? (0, verification_executable_1.verificationExecutable)(program, options.env) : program, args, {
87284
88090
  // Captured Git reads can contain NUL-delimited records that
87285
88091
  // hide subsequent lines in GitHub's Actions log viewer.
87286
88092
  ...(options.stdout ? { silent: true } : {}),
87287
88093
  ...(options.stdout ? { listeners: { stdout: options.stdout } } : {}),
87288
88094
  ...(options.env ? { env: options.env } : {}),
87289
88095
  })
87290
- : exec.exec(program, args), checkPrerequisites = verification_runtime_preflight_1.assertVerificationRuntimePrerequisites) {
88096
+ : exec.exec(program, args), checkPrerequisites = verification_runtime_preflight_1.assertVerificationRuntimePrerequisites, verificationSetup = verification_setup_ports_1.DISABLED_VERIFICATION_SETUP) {
87291
88097
  this.executeCommand = executeCommand;
87292
88098
  this.checkPrerequisites = checkPrerequisites;
88099
+ this.verificationSetup = verificationSetup;
87293
88100
  }
87294
88101
  async execute(program, args, options) {
87295
88102
  if (options?.verifyRuntimePrerequisites && !options.untrusted)
@@ -87300,15 +88107,19 @@ class GitCommitAdapter {
87300
88107
  throw new Error('Untrusted command execution does not accept a caller-supplied environment.');
87301
88108
  const runtime = (0, untrusted_command_environment_1.prepareUntrustedCommandEnvironment)();
87302
88109
  try {
87303
- if (options.verifyRuntimePrerequisites)
88110
+ if (options.verifyRuntimePrerequisites) {
88111
+ await (0, verification_setup_runner_1.prepareRepositoryVerification)(this.verificationSetup, runtime.environment);
87304
88112
  this.checkPrerequisites(runtime.environment);
88113
+ }
87305
88114
  return await this.executeCommand(program, args, {
87306
88115
  ...(options.stdout ? { stdout: options.stdout } : {}),
87307
88116
  env: runtime.environment,
88117
+ ...(options.verifyRuntimePrerequisites && this.verificationSetup.kind === 'ready' ? { resolveFromEnvironment: true } : {}),
87308
88118
  });
87309
88119
  }
87310
88120
  finally {
87311
- runtime.cleanup();
88121
+ if (!(0, native_verification_profiles_1.nativeVerificationRetainsProfile)(runtime.environment.HOME))
88122
+ runtime.cleanup();
87312
88123
  }
87313
88124
  }
87314
88125
  async configureAuthor(name, email) {
@@ -88004,6 +88815,659 @@ class LoggerWorkflowPollingObserverAdapter {
88004
88815
  exports.LoggerWorkflowPollingObserverAdapter = LoggerWorkflowPollingObserverAdapter;
88005
88816
 
88006
88817
 
88818
+ /***/ }),
88819
+
88820
+ /***/ 18883:
88821
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
88822
+
88823
+ "use strict";
88824
+
88825
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88826
+ exports.verificationCandidateIdentity = verificationCandidateIdentity;
88827
+ const node_child_process_1 = __nccwpck_require__(17718);
88828
+ const node_crypto_1 = __nccwpck_require__(6005);
88829
+ const node_fs_1 = __nccwpck_require__(87561);
88830
+ const node_path_1 = __nccwpck_require__(49411);
88831
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
88832
+ /** Bind setup to the exact HEAD, branch, index, tracked edits and publishable untracked files. */
88833
+ function verificationCandidateIdentity(workspace, environment) {
88834
+ const hash = (0, node_crypto_1.createHash)('sha256');
88835
+ const git = (...args) => {
88836
+ const result = (0, node_child_process_1.spawnSync)('git', ['--no-replace-objects', ...args], { cwd: workspace, env: environment, shell: false,
88837
+ windowsHide: true, timeout: 10000, maxBuffer: 16 * 1024 * 1024 });
88838
+ if (result.error || result.status !== 0)
88839
+ throw new verification_setup_policy_1.VerificationSetupError('candidate-changed');
88840
+ hash.update(result.stdout).update('\0');
88841
+ return result.stdout;
88842
+ };
88843
+ git('rev-parse', '--verify', 'HEAD');
88844
+ git('rev-parse', '--symbolic-full-name', 'HEAD');
88845
+ git('ls-files', '--stage', '-z');
88846
+ git('diff', '--no-ext-diff', '--no-textconv', '--binary', 'HEAD', '--');
88847
+ const paths = git('ls-files', '--others', '--exclude-standard', '-z').toString('utf8').split('\0').filter(Boolean);
88848
+ let total = 0;
88849
+ if (paths.length > 256)
88850
+ throw new verification_setup_policy_1.VerificationSetupError('candidate-changed');
88851
+ for (const path of paths) {
88852
+ const file = (0, node_path_1.join)(workspace, path);
88853
+ const stat = (0, node_fs_1.lstatSync)(file);
88854
+ total += stat.size;
88855
+ if (total > 16 * 1024 * 1024)
88856
+ throw new verification_setup_policy_1.VerificationSetupError('candidate-changed');
88857
+ hash.update(path).update('\0');
88858
+ if (stat.isSymbolicLink())
88859
+ hash.update('120000\0').update((0, node_fs_1.readlinkSync)(file));
88860
+ else if (stat.isFile())
88861
+ hash.update(stat.mode & 0o100 ? '100755\0' : '100644\0').update((0, node_fs_1.readFileSync)(file));
88862
+ else
88863
+ throw new verification_setup_policy_1.VerificationSetupError('candidate-changed');
88864
+ hash.update('\0');
88865
+ }
88866
+ return hash.digest('hex');
88867
+ }
88868
+
88869
+
88870
+ /***/ }),
88871
+
88872
+ /***/ 71046:
88873
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
88874
+
88875
+ "use strict";
88876
+
88877
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
88878
+ if (k2 === undefined) k2 = k;
88879
+ var desc = Object.getOwnPropertyDescriptor(m, k);
88880
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
88881
+ desc = { enumerable: true, get: function() { return m[k]; } };
88882
+ }
88883
+ Object.defineProperty(o, k2, desc);
88884
+ }) : (function(o, m, k, k2) {
88885
+ if (k2 === undefined) k2 = k;
88886
+ o[k2] = m[k];
88887
+ }));
88888
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
88889
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
88890
+ }) : function(o, v) {
88891
+ o["default"] = v;
88892
+ });
88893
+ var __importStar = (this && this.__importStar) || (function () {
88894
+ var ownKeys = function(o) {
88895
+ ownKeys = Object.getOwnPropertyNames || function (o) {
88896
+ var ar = [];
88897
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
88898
+ return ar;
88899
+ };
88900
+ return ownKeys(o);
88901
+ };
88902
+ return function (mod) {
88903
+ if (mod && mod.__esModule) return mod;
88904
+ var result = {};
88905
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
88906
+ __setModuleDefault(result, mod);
88907
+ return result;
88908
+ };
88909
+ })();
88910
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88911
+ exports.drainNativeWorkerLog = drainNativeWorkerLog;
88912
+ exports.awaitNativeBoundary = awaitNativeBoundary;
88913
+ exports.continueNativeVerification = continueNativeVerification;
88914
+ exports.cleanupNativeVerification = cleanupNativeVerification;
88915
+ exports.runNativeVerificationEntry = runNativeVerificationEntry;
88916
+ const native_verification_source_runtime_1 = __nccwpck_require__(85290);
88917
+ const verification_executable_1 = __nccwpck_require__(20878);
88918
+ const native_verification_redaction_1 = __nccwpck_require__(27632);
88919
+ const native_verification_profiles_1 = __nccwpck_require__(22290);
88920
+ const core = __importStar(__nccwpck_require__(75855));
88921
+ const node_child_process_1 = __nccwpck_require__(17718);
88922
+ const node_fs_1 = __nccwpck_require__(87561);
88923
+ const node_path_1 = __nccwpck_require__(49411);
88924
+ const agent_private_install_root_1 = __nccwpck_require__(44640);
88925
+ const agent_trusted_system_tools_1 = __nccwpck_require__(76049);
88926
+ const github_action_input_1 = __nccwpck_require__(57581);
88927
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
88928
+ const native_verification_protocol_1 = __nccwpck_require__(88709);
88929
+ const native_verification_staging_1 = __nccwpck_require__(63587);
88930
+ const verification_setup_snapshot_1 = __nccwpck_require__(62148);
88931
+ function emitWorkerOutput(root) {
88932
+ const file = (0, node_path_1.join)(root, 'worker-output');
88933
+ if (process.env.GITHUB_OUTPUT && (0, node_fs_1.existsSync)(file))
88934
+ (0, node_fs_1.appendFileSync)(process.env.GITHUB_OUTPUT, requireRead(file));
88935
+ const summary = (0, node_path_1.join)(root, 'worker-summary');
88936
+ if (process.env.GITHUB_STEP_SUMMARY && (0, node_fs_1.existsSync)(summary) && !(0, native_verification_protocol_1.readNativeRecord)(root, 'summary-emitted.json')) {
88937
+ (0, node_fs_1.appendFileSync)(process.env.GITHUB_STEP_SUMMARY, requireRead(summary, 1048576));
88938
+ (0, native_verification_protocol_1.writeNativeRecord)(root, 'summary-emitted.json', { emitted: true });
88939
+ }
88940
+ }
88941
+ function requireRead(file, limit = 262144) {
88942
+ const fd = (0, node_fs_1.openSync)(file, 'r');
88943
+ try {
88944
+ const size = (0, node_fs_1.statSync)(file).size;
88945
+ if (size > limit)
88946
+ throw new verification_setup_policy_1.VerificationSetupError('output-limit');
88947
+ const data = Buffer.alloc(size);
88948
+ (0, node_fs_1.readSync)(fd, data, 0, data.length, 0);
88949
+ return data;
88950
+ }
88951
+ finally {
88952
+ (0, node_fs_1.closeSync)(fd);
88953
+ }
88954
+ }
88955
+ /** Drain complete lines so runner masking and workflow commands keep their native framing. */
88956
+ function drainNativeWorkerLog(root, flush = false) {
88957
+ const file = (0, node_path_1.join)(root, 'worker-log');
88958
+ if (!(0, node_fs_1.existsSync)(file))
88959
+ return;
88960
+ const cursor = (0, native_verification_protocol_1.readNativeRecord)(root, 'log-cursor.json')?.offset ?? 0;
88961
+ const fd = (0, node_fs_1.openSync)(file, 'r');
88962
+ let offset = cursor;
88963
+ try {
88964
+ const buffer = Buffer.alloc(65536);
88965
+ let pending = Buffer.alloc(0);
88966
+ let size;
88967
+ while ((size = (0, node_fs_1.readSync)(fd, buffer, 0, buffer.length, offset + pending.length))) {
88968
+ pending = Buffer.concat([pending, buffer.subarray(0, size)]);
88969
+ const lastLine = pending.lastIndexOf(10);
88970
+ if (lastLine >= 0) {
88971
+ const complete = pending.subarray(0, lastLine + 1);
88972
+ process.stdout.write(complete);
88973
+ offset += complete.length;
88974
+ pending = pending.subarray(lastLine + 1);
88975
+ }
88976
+ // Existing action logs may contain long lines; retain framing without unbounded buffering.
88977
+ if (pending.length > 1048576)
88978
+ throw new verification_setup_policy_1.VerificationSetupError('output-limit');
88979
+ }
88980
+ if (flush && pending.length) {
88981
+ process.stdout.write(pending);
88982
+ offset += pending.length;
88983
+ }
88984
+ (0, native_verification_protocol_1.writeNativeRecord)(root, 'log-cursor.json', { offset });
88985
+ }
88986
+ finally {
88987
+ (0, node_fs_1.closeSync)(fd);
88988
+ }
88989
+ }
88990
+ async function awaitNativeBoundary(root, timeoutMs = 7200000) {
88991
+ const deadline = Date.now() + timeoutMs;
88992
+ while (true) {
88993
+ drainNativeWorkerLog(root);
88994
+ const done = (0, native_verification_protocol_1.readNativeRecord)(root, 'done.json');
88995
+ if (done) {
88996
+ drainNativeWorkerLog(root, true);
88997
+ emitWorkerOutput(root);
88998
+ core.setOutput('verification-setup-pending', 'false');
88999
+ if (done.exitCode !== 0)
89000
+ core.setFailed('Copilot execution failed; inspect the preceding operation result.');
89001
+ return;
89002
+ }
89003
+ const request = (0, native_verification_protocol_1.readNativeRecord)(root, 'request.json', 32768);
89004
+ if (request) {
89005
+ if (!/^[a-f0-9-]{36}$/u.test(request.id) || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u.test(request.sourceSha)
89006
+ || !/^[a-f0-9]{64}$/u.test(request.digest) || !request.environment || typeof request.environment.HOME !== 'string')
89007
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89008
+ core.setOutput('verification-request', request.id);
89009
+ core.setOutput('verification-source', request.sourceSha);
89010
+ core.setOutput('verification-digest', request.digest);
89011
+ core.saveState('native-verification-digest', request.digest);
89012
+ core.saveState('native-verification-source', request.sourceSha);
89013
+ for (const key of ['HOME', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'PATH', 'JAVA_HOME', 'TMP', 'TEMP', 'TMPDIR']) {
89014
+ const value = request.environment[key] ?? '';
89015
+ if (typeof value !== 'string' || /[\r\n\0]/u.test(value))
89016
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89017
+ core.setOutput(`verification-${key.toLowerCase()}`, value);
89018
+ }
89019
+ core.setOutput('verification-setup-pending', 'true');
89020
+ return;
89021
+ }
89022
+ if (Date.now() >= deadline)
89023
+ throw new verification_setup_policy_1.VerificationSetupError('timeout');
89024
+ const session = (0, native_verification_protocol_1.nativeSession)(root);
89025
+ try {
89026
+ process.kill(session.pid, 0);
89027
+ }
89028
+ catch {
89029
+ throw new verification_setup_policy_1.VerificationSetupError('process-failed');
89030
+ }
89031
+ await (0, native_verification_protocol_1.nativePause)(100);
89032
+ }
89033
+ }
89034
+ async function continueNativeVerification(root, id, outcome, environment = process.env) {
89035
+ (0, native_verification_protocol_1.nativeSession)(root);
89036
+ const request = (0, native_verification_protocol_1.readNativeRecord)(root, 'request.json', 32768);
89037
+ if (!request || request.id !== id || !/^[a-f0-9-]{36}$/u.test(id)
89038
+ || (0, node_fs_1.existsSync)((0, node_path_1.join)(root, `response-${id}.json`)))
89039
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89040
+ const response = { id, success: outcome === 'success', path: environment.PATH ?? '',
89041
+ ...(environment.JAVA_HOME ? { javaHome: environment.JAVA_HOME } : {}) };
89042
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(root, 'request.json'));
89043
+ (0, native_verification_protocol_1.writeNativeRecord)(root, `response-${id}.json`, response);
89044
+ await awaitNativeBoundary(root);
89045
+ }
89046
+ async function cleanupNativeVerification(root, waitMs = 10000, deferProfileCleanup = false) {
89047
+ if (!(0, node_fs_1.existsSync)(root))
89048
+ return;
89049
+ const session = (0, native_verification_protocol_1.nativeSession)(root);
89050
+ if (!(0, native_verification_protocol_1.readNativeRecord)(root, 'done.json')) {
89051
+ (0, native_verification_protocol_1.writeNativeRecord)(root, 'cancel.json', { cancelled: true });
89052
+ const deadline = Date.now() + waitMs;
89053
+ while (!(0, native_verification_protocol_1.readNativeRecord)(root, 'done.json') && Date.now() < deadline)
89054
+ await (0, native_verification_protocol_1.nativePause)(100);
89055
+ if (!(0, native_verification_protocol_1.readNativeRecord)(root, 'done.json')) {
89056
+ try {
89057
+ if (process.platform === 'win32')
89058
+ (0, node_child_process_1.spawnSync)((0, agent_trusted_system_tools_1.trustedWindowsSystemTool)('taskkill.exe'), ['/PID', String(session.pid), '/T', '/F'], { windowsHide: true, shell: false, timeout: 5000, stdio: 'ignore' });
89059
+ else
89060
+ process.kill(-session.pid, 'SIGKILL');
89061
+ }
89062
+ catch { /* Worker may have exited while cancellation completed. */ }
89063
+ }
89064
+ }
89065
+ if (!deferProfileCleanup)
89066
+ (0, native_verification_staging_1.cleanupNativeVerificationAction)(root, session.workspace);
89067
+ drainNativeWorkerLog(root, true);
89068
+ if (!deferProfileCleanup) {
89069
+ (0, native_verification_profiles_1.removeNativeVerificationProfiles)(root);
89070
+ (0, node_fs_1.rmSync)(root, { recursive: true, force: true });
89071
+ }
89072
+ }
89073
+ async function startNativeVerification() {
89074
+ for (const secret of (0, native_verification_redaction_1.nativeWorkerSecrets)(process.env))
89075
+ core.setSecret(secret);
89076
+ const git = (0, verification_executable_1.verificationExecutable)('git', { PATH: process.env.PATH ?? '', PATHEXT: process.env.PATHEXT ?? '.EXE;.CMD;.BAT;.COM' });
89077
+ core.saveState('native-verification-git', git);
89078
+ core.setOutput('verification-git', git);
89079
+ const root = (0, node_fs_1.realpathSync)((0, agent_private_install_root_1.createPrivateVerificationRuntimeRoot)());
89080
+ for (const name of ['worker-output', 'worker-env', 'worker-path', 'worker-log', 'worker-summary'])
89081
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(root, name), '', { flag: 'wx', mode: 0o600 });
89082
+ const log = (0, node_fs_1.openSync)((0, node_path_1.join)(root, 'worker-log'), 'a');
89083
+ try {
89084
+ const worker = (0, node_child_process_1.spawn)(process.execPath, [process.argv[1]], { cwd: process.cwd(), detached: true, windowsHide: true,
89085
+ stdio: ['ignore', log, log], env: { ...process.env, COPILOT_NATIVE_PHASE: '', COPILOT_NATIVE_WORKER_SESSION: root,
89086
+ GITHUB_STEP_SUMMARY: (0, node_path_1.join)(root, 'worker-summary'), GITHUB_OUTPUT: (0, node_path_1.join)(root, 'worker-output'), GITHUB_ENV: (0, node_path_1.join)(root, 'worker-env'), GITHUB_PATH: (0, node_path_1.join)(root, 'worker-path') } });
89087
+ await new Promise((resolve, reject) => { worker.once('spawn', resolve); worker.once('error', reject); });
89088
+ worker.unref();
89089
+ (0, native_verification_protocol_1.writeNativeRecord)(root, 'session.json', { schemaVersion: 1, workspace: (0, node_fs_1.realpathSync)(process.cwd()), run: process.env.GITHUB_RUN_ID ?? '',
89090
+ attempt: process.env.GITHUB_RUN_ATTEMPT ?? '', job: process.env.GITHUB_JOB ?? '', pid: worker.pid });
89091
+ core.saveState('native-verification-ticket', root);
89092
+ core.saveState('native-verification-owner', 'true');
89093
+ core.setOutput('verification-ticket', root);
89094
+ await awaitNativeBoundary(root);
89095
+ }
89096
+ catch (error) {
89097
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(root, 'session.json')))
89098
+ await cleanupNativeVerification(root);
89099
+ else
89100
+ (0, node_fs_1.rmSync)(root, { recursive: true, force: true });
89101
+ throw error;
89102
+ }
89103
+ finally {
89104
+ (0, node_fs_1.closeSync)(log);
89105
+ }
89106
+ }
89107
+ /** Native phases are runner-only control messages; no credentials or agent operations are replayed. */
89108
+ async function runNativeVerificationEntry(run) {
89109
+ const post = core.getState('copilot-native-post');
89110
+ if (post === 'true') {
89111
+ const root = core.getState('native-verification-ticket');
89112
+ if (root && core.getState('native-verification-owner') === 'true')
89113
+ await cleanupNativeVerification(root);
89114
+ else if (root && (0, node_fs_1.existsSync)(root) && core.getState('native-verification-source')) {
89115
+ const session = (0, native_verification_protocol_1.nativeSession)(root);
89116
+ try {
89117
+ const snapshot = (0, verification_setup_snapshot_1.captureVerificationSetupAtCommit)(core.getState('native-verification-source'), session.workspace, core.getState('native-verification-git'));
89118
+ if (snapshot.kind !== 'ready' || (0, verification_setup_snapshot_1.verificationSetupDigest)(snapshot) !== core.getState('native-verification-digest'))
89119
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
89120
+ (0, native_verification_staging_1.stageNativeVerificationAction)(snapshot, root);
89121
+ }
89122
+ catch {
89123
+ // A later native post must fail to load rather than execute candidate-modified metadata.
89124
+ (0, native_verification_staging_1.cleanupNativeVerificationAction)(root, session.workspace);
89125
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
89126
+ }
89127
+ }
89128
+ const sourceRuntime = core.getState('native-source-runtime');
89129
+ if (sourceRuntime)
89130
+ (0, native_verification_source_runtime_1.cleanupNativeSourceRuntime)(sourceRuntime, (0, node_fs_1.realpathSync)(process.cwd()));
89131
+ return;
89132
+ }
89133
+ core.saveState('copilot-native-post', 'true');
89134
+ if (process.env.COPILOT_NATIVE_PHASE === 'prepare' && process.env.COPILOT_NATIVE_RUNTIME_CACHE)
89135
+ core.saveState('native-source-runtime', process.env.COPILOT_NATIVE_RUNTIME_CACHE);
89136
+ const worker = process.env.COPILOT_NATIVE_WORKER_SESSION;
89137
+ if (worker) {
89138
+ const deadline = Date.now() + 30000;
89139
+ while (!(0, native_verification_protocol_1.readNativeRecord)(worker, 'session.json')) {
89140
+ if (Date.now() >= deadline)
89141
+ throw new verification_setup_policy_1.VerificationSetupError('timeout');
89142
+ await (0, native_verification_protocol_1.nativePause)(10);
89143
+ }
89144
+ if ((0, native_verification_protocol_1.nativeSession)(worker).pid !== process.pid)
89145
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89146
+ const restoreLog = (0, native_verification_redaction_1.redactNativeWorkerLogs)();
89147
+ try {
89148
+ await run();
89149
+ }
89150
+ finally {
89151
+ restoreLog();
89152
+ (0, native_verification_protocol_1.writeNativeRecord)(worker, 'done.json', { exitCode: Number(process.exitCode ?? 0) });
89153
+ }
89154
+ return;
89155
+ }
89156
+ const phase = process.env.COPILOT_NATIVE_PHASE;
89157
+ if (!phase || phase === 'prepare' && (0, github_action_input_1.getGithubActionInput)('verification-setup') !== 'true') {
89158
+ await run();
89159
+ return;
89160
+ }
89161
+ if (process.env.GITHUB_ACTIONS !== 'true')
89162
+ throw new verification_setup_policy_1.VerificationSetupError('native-workflow-required');
89163
+ if (phase === 'prepare') {
89164
+ await startNativeVerification();
89165
+ return;
89166
+ }
89167
+ const root = process.env.COPILOT_NATIVE_TICKET;
89168
+ if (!root)
89169
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89170
+ (0, native_verification_protocol_1.nativeSession)(root);
89171
+ core.saveState('native-verification-ticket', root);
89172
+ core.saveState('native-verification-source', process.env.COPILOT_NATIVE_SOURCE ?? '');
89173
+ core.saveState('native-verification-digest', process.env.COPILOT_NATIVE_DIGEST ?? '');
89174
+ core.saveState('native-verification-git', process.env.COPILOT_NATIVE_GIT ?? '');
89175
+ if (phase === 'continue') {
89176
+ await continueNativeVerification(root, process.env.COPILOT_NATIVE_REQUEST ?? '', process.env.COPILOT_NATIVE_OUTCOME ?? '');
89177
+ return;
89178
+ }
89179
+ if (phase === 'finish') {
89180
+ (0, native_verification_protocol_1.nativeSession)(root);
89181
+ const done = (0, native_verification_protocol_1.readNativeRecord)(root, 'done.json');
89182
+ if (done) {
89183
+ emitWorkerOutput(root);
89184
+ if (done.exitCode !== 0)
89185
+ core.setFailed('Copilot execution failed.');
89186
+ }
89187
+ else
89188
+ core.setFailed(`Repository setup did not complete within ${verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.requests} native verification boundaries. Pending verification and subsequent publication are blocked; inspect earlier operation results for completed effects.`);
89189
+ await cleanupNativeVerification(root, 10000, true);
89190
+ return;
89191
+ }
89192
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89193
+ }
89194
+
89195
+
89196
+ /***/ }),
89197
+
89198
+ /***/ 22290:
89199
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
89200
+
89201
+ "use strict";
89202
+
89203
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89204
+ exports.nativeVerificationProfilePaths = nativeVerificationProfilePaths;
89205
+ exports.registerNativeVerificationProfile = registerNativeVerificationProfile;
89206
+ exports.nativeVerificationRetainsProfile = nativeVerificationRetainsProfile;
89207
+ exports.removeNativeVerificationProfiles = removeNativeVerificationProfiles;
89208
+ const node_crypto_1 = __nccwpck_require__(6005);
89209
+ const node_fs_1 = __nccwpck_require__(87561);
89210
+ const node_path_1 = __nccwpck_require__(49411);
89211
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
89212
+ const native_verification_protocol_1 = __nccwpck_require__(88709);
89213
+ function nativeVerificationProfilePaths(root) {
89214
+ const stored = (0, native_verification_protocol_1.readNativeRecord)(root, 'profiles.json', 65536);
89215
+ const paths = stored === undefined ? [] : stored;
89216
+ if (!Array.isArray(paths) || paths.length > 20 || new Set(paths).size !== paths.length || paths.some(path => typeof path !== 'string'
89217
+ || (0, node_path_1.dirname)(path) !== (0, node_path_1.dirname)(root) || !/^copilot-verify-runtime-[A-Za-z0-9]+$/u.test((0, node_path_1.basename)(path)) || path === root))
89218
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89219
+ return paths;
89220
+ }
89221
+ /** Native actions may have post steps. Preserve dependency-only profiles until those steps finish. */
89222
+ function registerNativeVerificationProfile(root, profile) {
89223
+ const previous = nativeVerificationProfilePaths(root);
89224
+ if (previous.length >= 20 || previous.includes(profile) || (0, node_path_1.dirname)(profile) !== (0, node_path_1.dirname)(root)
89225
+ || profile === root || !/^copilot-verify-runtime-[A-Za-z0-9]+$/u.test((0, node_path_1.basename)(profile))
89226
+ || (0, node_fs_1.realpathSync)(profile) !== profile || !(0, node_fs_1.lstatSync)(profile).isDirectory() || (0, node_fs_1.lstatSync)(profile).isSymbolicLink())
89227
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89228
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(profile, 'native-session-owner'), (0, node_crypto_1.createHash)('sha256').update(root).digest('hex'), { mode: 0o600, flag: 'wx' });
89229
+ (0, native_verification_protocol_1.writeNativeRecord)(root, 'profiles.json', [...previous, profile]);
89230
+ }
89231
+ function nativeVerificationRetainsProfile(profile) {
89232
+ const root = process.env.COPILOT_NATIVE_WORKER_SESSION;
89233
+ return !!root && nativeVerificationProfilePaths(root).includes(profile);
89234
+ }
89235
+ function removeNativeVerificationProfiles(root) {
89236
+ for (const path of nativeVerificationProfilePaths(root)) {
89237
+ let stat;
89238
+ try {
89239
+ stat = (0, node_fs_1.lstatSync)(path);
89240
+ }
89241
+ catch (error) {
89242
+ if (error.code === 'ENOENT')
89243
+ continue;
89244
+ throw error;
89245
+ }
89246
+ if (!stat.isDirectory() || stat.isSymbolicLink() || (0, node_fs_1.realpathSync)(path) !== path || (0, node_fs_1.readFileSync)((0, node_path_1.join)(path, 'native-session-owner'), 'utf8') !== (0, node_crypto_1.createHash)('sha256').update(root).digest('hex'))
89247
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89248
+ (0, node_fs_1.rmSync)(path, { recursive: true, force: true });
89249
+ }
89250
+ }
89251
+
89252
+
89253
+ /***/ }),
89254
+
89255
+ /***/ 88709:
89256
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
89257
+
89258
+ "use strict";
89259
+
89260
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89261
+ exports.nativePause = void 0;
89262
+ exports.writeNativeRecord = writeNativeRecord;
89263
+ exports.readNativeRecord = readNativeRecord;
89264
+ exports.nativeSession = nativeSession;
89265
+ const node_fs_1 = __nccwpck_require__(87561);
89266
+ const node_path_1 = __nccwpck_require__(49411);
89267
+ const node_crypto_1 = __nccwpck_require__(6005);
89268
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
89269
+ function writeNativeRecord(root, name, value) {
89270
+ const temporary = (0, node_path_1.join)(root, `${(0, node_crypto_1.randomUUID)()}.tmp`);
89271
+ (0, node_fs_1.writeFileSync)(temporary, JSON.stringify(value), { mode: 0o600, flag: 'wx' });
89272
+ (0, node_fs_1.renameSync)(temporary, (0, node_path_1.join)(root, name));
89273
+ }
89274
+ function readNativeRecord(root, name, limit = 16384) {
89275
+ const file = (0, node_path_1.join)(root, name);
89276
+ let descriptor;
89277
+ try {
89278
+ const before = (0, node_fs_1.lstatSync)(file, { bigint: true });
89279
+ if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n || before.size > BigInt(limit))
89280
+ throw new Error();
89281
+ descriptor = (0, node_fs_1.openSync)(file, node_fs_1.constants.O_RDONLY | (node_fs_1.constants.O_NOFOLLOW ?? 0));
89282
+ const after = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
89283
+ if (after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs)
89284
+ throw new Error();
89285
+ const data = (0, node_fs_1.readFileSync)(descriptor);
89286
+ const final = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
89287
+ if (data.length > limit || final.size !== after.size || final.mtimeNs !== after.mtimeNs)
89288
+ throw new Error();
89289
+ return JSON.parse(data.toString('utf8'));
89290
+ }
89291
+ catch (error) {
89292
+ if (error.code === 'ENOENT')
89293
+ return undefined;
89294
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89295
+ }
89296
+ finally {
89297
+ if (descriptor !== undefined)
89298
+ (0, node_fs_1.closeSync)(descriptor);
89299
+ }
89300
+ }
89301
+ function nativeSession(root, environment = process.env) {
89302
+ if (!/^copilot-verify-runtime-[A-Za-z0-9]+$/u.test((0, node_path_1.basename)(root)) || (0, node_fs_1.realpathSync)(root) !== root
89303
+ || !(0, node_fs_1.lstatSync)(root).isDirectory() || (0, node_fs_1.lstatSync)(root).isSymbolicLink())
89304
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89305
+ if (process.platform !== 'win32' && ((0, node_fs_1.lstatSync)(root).mode & 0o077) !== 0)
89306
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89307
+ const session = readNativeRecord(root, 'session.json');
89308
+ if (session?.schemaVersion !== 1 || session.workspace !== (0, node_fs_1.realpathSync)(process.cwd())
89309
+ || session.run !== (environment.GITHUB_RUN_ID ?? '') || session.attempt !== (environment.GITHUB_RUN_ATTEMPT ?? '')
89310
+ || session.job !== (environment.GITHUB_JOB ?? '') || !Number.isSafeInteger(session.pid) || session.pid <= 0)
89311
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89312
+ return session;
89313
+ }
89314
+ const nativePause = (milliseconds) => new Promise(resolve => setTimeout(resolve, milliseconds));
89315
+ exports.nativePause = nativePause;
89316
+
89317
+
89318
+ /***/ }),
89319
+
89320
+ /***/ 27632:
89321
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
89322
+
89323
+ "use strict";
89324
+
89325
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89326
+ exports.nativeWorkerSecrets = nativeWorkerSecrets;
89327
+ exports.redactNativeWorkerLogs = redactNativeWorkerLogs;
89328
+ const node_string_decoder_1 = __nccwpck_require__(76915);
89329
+ const SECRET_KEY = /(?:TOKEN|SECRET|API_KEY|PASSWORD|AUTH_JSON)/iu;
89330
+ function nativeWorkerSecrets(environment) {
89331
+ const values = Object.entries(environment).filter(([key, value]) => SECRET_KEY.test(key) && value).map(([, value]) => value);
89332
+ if (environment.INPUT_VARS_JSON) {
89333
+ try {
89334
+ const inputs = JSON.parse(environment.INPUT_VARS_JSON);
89335
+ for (const [key, value] of Object.entries(inputs))
89336
+ if (SECRET_KEY.test(key) && typeof value === 'string')
89337
+ values.push(value);
89338
+ }
89339
+ catch { /* The existing input parser reports invalid configuration without raw values. */ }
89340
+ }
89341
+ return [...new Set(values.flatMap(value => [value, ...value.split(/[\r\n]/u)]).filter(value => value.length >= 3))].sort((a, b) => b.length - a.length);
89342
+ }
89343
+ /** Secrets are removed before bytes reach a private log file, not merely masked in the runner UI. */
89344
+ function redactNativeWorkerLogs(environment = process.env) {
89345
+ const secrets = nativeWorkerSecrets(environment);
89346
+ const restores = [];
89347
+ for (const stream of [process.stdout, process.stderr]) {
89348
+ const original = stream.write;
89349
+ const decoder = new node_string_decoder_1.StringDecoder('utf8');
89350
+ let pending = '';
89351
+ const emit = (line) => {
89352
+ const command = /^::add-mask::(.*?)(?:\r?\n)?$/u.exec(line);
89353
+ if (command) {
89354
+ const value = command[1].replace(/%0D/gu, '\r').replace(/%0A/gu, '\n').replace(/%25/gu, '%');
89355
+ secrets.push(...value.split(/[\r\n]/u).filter(part => part.length >= 3));
89356
+ return;
89357
+ }
89358
+ for (const secret of secrets)
89359
+ line = line.split(secret).join('[REDACTED]');
89360
+ original.call(stream, line);
89361
+ };
89362
+ stream.write = ((chunk, encoding, callback) => {
89363
+ pending += typeof chunk === 'string' ? chunk : decoder.write(Buffer.from(chunk));
89364
+ let end;
89365
+ while ((end = pending.indexOf('\n')) >= 0) {
89366
+ const line = pending.slice(0, end + 1);
89367
+ pending = pending.slice(end + 1);
89368
+ emit(line);
89369
+ }
89370
+ if (pending.length > 1048576)
89371
+ throw new Error('Copilot worker log line exceeded its fixed limit.');
89372
+ if (typeof encoding === 'function')
89373
+ encoding();
89374
+ else
89375
+ callback?.();
89376
+ return true;
89377
+ });
89378
+ restores.push(() => { pending += decoder.end(); if (pending)
89379
+ emit(pending); stream.write = original; });
89380
+ }
89381
+ return () => { for (const restore of restores)
89382
+ restore(); };
89383
+ }
89384
+
89385
+
89386
+ /***/ }),
89387
+
89388
+ /***/ 85290:
89389
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
89390
+
89391
+ "use strict";
89392
+
89393
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89394
+ exports.cleanupNativeSourceRuntime = cleanupNativeSourceRuntime;
89395
+ const node_fs_1 = __nccwpck_require__(87561);
89396
+ const node_path_1 = __nccwpck_require__(49411);
89397
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
89398
+ /** Only source workflows use this snapshot; installed remote Actions already live outside the candidate. */
89399
+ function cleanupNativeSourceRuntime(root, workspace) {
89400
+ if (!root || !(0, node_fs_1.existsSync)(root))
89401
+ return;
89402
+ const allowed = ['.copilot-native-runtime', '.copilot-native-fixture-runtime'].map(name => (0, node_path_1.join)((0, node_path_1.dirname)(workspace), name));
89403
+ if (!allowed.includes(root) || (0, node_fs_1.lstatSync)(root).isSymbolicLink() || (0, node_fs_1.realpathSync)(root) !== root)
89404
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89405
+ let receipt;
89406
+ try {
89407
+ receipt = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(root, '.copilot-runtime-snapshot.json'), 'utf8'));
89408
+ }
89409
+ catch {
89410
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89411
+ }
89412
+ if (receipt?.kind !== 'copilot-native-runtime' || receipt.workspace !== workspace)
89413
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89414
+ (0, node_fs_1.rmSync)(root, { recursive: true, force: true });
89415
+ }
89416
+
89417
+
89418
+ /***/ }),
89419
+
89420
+ /***/ 63587:
89421
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
89422
+
89423
+ "use strict";
89424
+
89425
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89426
+ exports.NATIVE_VERIFICATION_ACTION = void 0;
89427
+ exports.stageNativeVerificationAction = stageNativeVerificationAction;
89428
+ exports.cleanupNativeVerificationAction = cleanupNativeVerificationAction;
89429
+ const node_fs_1 = __nccwpck_require__(87561);
89430
+ const node_path_1 = __nccwpck_require__(49411);
89431
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
89432
+ const native_verification_protocol_1 = __nccwpck_require__(88709);
89433
+ exports.NATIVE_VERIFICATION_ACTION = '.git/copilot-verification-setup';
89434
+ function targetPath(workspace) {
89435
+ const metadata = (0, node_path_1.join)(workspace, '.git');
89436
+ const stat = (0, node_fs_1.lstatSync)(metadata);
89437
+ if (!stat.isDirectory() || stat.isSymbolicLink() || (0, node_fs_1.realpathSync)(metadata) !== metadata)
89438
+ throw new verification_setup_policy_1.VerificationSetupError('native-workflow-required');
89439
+ return (0, node_path_1.join)(workspace, exports.NATIVE_VERIFICATION_ACTION);
89440
+ }
89441
+ /** Native composite metadata must remain available until its deferred post steps have finished. */
89442
+ function stageNativeVerificationAction(setup, session) {
89443
+ const target = targetPath(setup.workspace);
89444
+ const record = (0, native_verification_protocol_1.readNativeRecord)(session, 'staging.json');
89445
+ if (record && record.target !== target || !record && !!(0, node_fs_1.lstatSync)(target, { throwIfNoEntry: false }))
89446
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89447
+ (0, native_verification_protocol_1.writeNativeRecord)(session, 'staging.json', { target });
89448
+ (0, node_fs_1.rmSync)(target, { recursive: true, force: true });
89449
+ (0, node_fs_1.mkdirSync)(target, { mode: 0o700 });
89450
+ for (const file of setup.files) {
89451
+ const destination = (0, node_path_1.join)(target, file.path);
89452
+ const remainder = (0, node_path_1.relative)(target, destination);
89453
+ if (!remainder || remainder.startsWith(`..${node_path_1.sep}`) || remainder === '..')
89454
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
89455
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(destination), { recursive: true, mode: 0o700 });
89456
+ (0, node_fs_1.writeFileSync)(destination, Buffer.from(file.base64, 'base64'), { mode: file.executable ? 0o700 : 0o600, flag: 'wx' });
89457
+ }
89458
+ }
89459
+ function cleanupNativeVerificationAction(session, workspace) {
89460
+ const record = (0, native_verification_protocol_1.readNativeRecord)(session, 'staging.json');
89461
+ if (!record)
89462
+ return;
89463
+ const target = targetPath(workspace);
89464
+ if (record.target !== target)
89465
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
89466
+ (0, node_fs_1.rmSync)(target, { recursive: true, force: true });
89467
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(session, 'staging.json'), { force: true });
89468
+ }
89469
+
89470
+
88007
89471
  /***/ }),
88008
89472
 
88009
89473
  /***/ 35849:
@@ -88053,6 +89517,7 @@ const node_crypto_1 = __nccwpck_require__(6005);
88053
89517
  const node_child_process_1 = __nccwpck_require__(17718);
88054
89518
  const node_util_1 = __nccwpck_require__(47261);
88055
89519
  const pre_branch_sdd_1 = __nccwpck_require__(34730);
89520
+ const sdd_draft_consistency_1 = __nccwpck_require__(27910);
88056
89521
  const git_authentication_environment_1 = __nccwpck_require__(16535);
88057
89522
  const git_hook_isolation_1 = __nccwpck_require__(39764);
88058
89523
  const runFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
@@ -88126,6 +89591,17 @@ class PreBranchSddWorkspaceAdapter {
88126
89591
  if (fs.existsSync(target) !== (plan.action === 'update')) {
88127
89592
  throw new Error('The SDD owner changed since analysis; restart clarification.');
88128
89593
  }
89594
+ const owners = [];
89595
+ const inventory = await this.inventoryAt(snapshot.baseSha);
89596
+ for (const file of snapshot.capabilities.find(capability => capability.id === plan.capabilityId)?.specs ?? []) {
89597
+ if (!(0, pre_branch_sdd_1.isSafeSddPath)(file))
89598
+ throw new Error('An owning SDD path is unsafe.');
89599
+ if (!inventory.files.has(file))
89600
+ throw new Error('An owning SDD is not a regular file at the immutable base.');
89601
+ assertRegularSpecFile(path.join(root, file));
89602
+ owners.push({ path: file, markdown: await this.git(['show', `${snapshot.baseSha}:${file}`]) });
89603
+ }
89604
+ (0, sdd_draft_consistency_1.validateSddDraftConsistency)(markdown, owners, inventory, plan.path);
88129
89605
  if (plan.action === 'update') {
88130
89606
  assertRegularSpecFile(target);
88131
89607
  const owner = await this.git(['show', `${snapshot.baseSha}:${plan.path}`]);
@@ -88264,7 +89740,13 @@ class PreBranchSddWorkspaceAdapter {
88264
89740
  const raw = await this.git(['show', `${first}:specs/catalog.json`]);
88265
89741
  newCapability = JSON.parse(raw).capabilities.find(capability => capability.id === prepared.plan.capabilityId);
88266
89742
  }
88267
- const recovered = await this.validateDraft(snapshot, prepared.plan, content, newCapability);
89743
+ const candidate = prepared.plan.action === 'update'
89744
+ ? (0, pre_branch_sdd_1.recoverSddUpdate)(await this.git(['show', `${prepared.baseSha}:${prepared.plan.path}`]), content) : content;
89745
+ if (!candidate)
89746
+ return undefined;
89747
+ const recovered = await this.validateDraft(snapshot, prepared.plan, candidate, newCapability);
89748
+ if (recovered.markdown !== content)
89749
+ return undefined;
88268
89750
  const committedPaths = (await this.git(['diff-tree', '--no-commit-id', '--name-only', '-r', first])).trim().split('\n').filter(Boolean).sort();
88269
89751
  if (committedPaths.join('\n') !== recovered.changedPaths.join('\n'))
88270
89752
  return undefined;
@@ -88299,6 +89781,25 @@ class PreBranchSddWorkspaceAdapter {
88299
89781
  const output = await this.git(['status', '--porcelain', '--untracked-files=all'], root);
88300
89782
  return output.split('\n').filter(Boolean).map(line => line.slice(3)).sort();
88301
89783
  }
89784
+ async inventoryAt(sha) {
89785
+ const files = new Set();
89786
+ const directories = new Set();
89787
+ const blocked = new Set();
89788
+ const tree = await this.git(['ls-tree', '-rz', '--full-tree', sha]);
89789
+ for (const entry of tree.split('\0').filter(Boolean)) {
89790
+ const tab = entry.indexOf('\t');
89791
+ const file = entry.slice(tab + 1);
89792
+ const mode = entry.slice(0, 6);
89793
+ if (mode === '100644' || mode === '100755')
89794
+ files.add(file);
89795
+ else
89796
+ blocked.add(file);
89797
+ const parts = file.split('/');
89798
+ for (let index = 1; index < parts.length; index++)
89799
+ directories.add(parts.slice(0, index).join('/'));
89800
+ }
89801
+ return { files, directories, blocked };
89802
+ }
88302
89803
  async addDetachedWorktree(sha) {
88303
89804
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'copilot-sdd-'));
88304
89805
  try {
@@ -88405,6 +89906,190 @@ function writeSpecFile(target, content, exists) {
88405
89906
  }
88406
89907
 
88407
89908
 
89909
+ /***/ }),
89910
+
89911
+ /***/ 12471:
89912
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
89913
+
89914
+ "use strict";
89915
+
89916
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
89917
+ if (k2 === undefined) k2 = k;
89918
+ var desc = Object.getOwnPropertyDescriptor(m, k);
89919
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
89920
+ desc = { enumerable: true, get: function() { return m[k]; } };
89921
+ }
89922
+ Object.defineProperty(o, k2, desc);
89923
+ }) : (function(o, m, k, k2) {
89924
+ if (k2 === undefined) k2 = k;
89925
+ o[k2] = m[k];
89926
+ }));
89927
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
89928
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
89929
+ }) : function(o, v) {
89930
+ o["default"] = v;
89931
+ });
89932
+ var __importStar = (this && this.__importStar) || (function () {
89933
+ var ownKeys = function(o) {
89934
+ ownKeys = Object.getOwnPropertyNames || function (o) {
89935
+ var ar = [];
89936
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
89937
+ return ar;
89938
+ };
89939
+ return ownKeys(o);
89940
+ };
89941
+ return function (mod) {
89942
+ if (mod && mod.__esModule) return mod;
89943
+ var result = {};
89944
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
89945
+ __setModuleDefault(result, mod);
89946
+ return result;
89947
+ };
89948
+ })();
89949
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
89950
+ exports.inspectSetupVerificationActionPath = inspectSetupVerificationActionPath;
89951
+ exports.readSetupVerificationActionStarter = readSetupVerificationActionStarter;
89952
+ exports.createSetupVerificationAction = createSetupVerificationAction;
89953
+ const fs = __importStar(__nccwpck_require__(87561));
89954
+ const node_path_1 = __nccwpck_require__(49411);
89955
+ const setup_verification_action_1 = __nccwpck_require__(33156);
89956
+ const unsafe = () => new Error(`${setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH}: setup requires real parent directories and a regular action file. Inspect the path and remove unsafe links or collisions, then review setup again. Existing contents were preserved.`);
89957
+ const stale = () => new Error(`${setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH}: the path changed after review. No existing action was replaced. Review a fresh setup plan.`);
89958
+ const sameDirectory = (left, right) => left.ino > 0n
89959
+ && left.dev === right.dev && left.ino === right.ino;
89960
+ const directoryFlags = fs.constants.O_RDONLY | (fs.constants.O_DIRECTORY ?? 0)
89961
+ | (fs.constants.O_NOFOLLOW ?? 0) | (fs.constants.O_NONBLOCK ?? 0);
89962
+ function entry(path) {
89963
+ try {
89964
+ return fs.lstatSync(path, { bigint: true });
89965
+ }
89966
+ catch (error) {
89967
+ if (error.code === 'ENOENT')
89968
+ return undefined;
89969
+ throw error;
89970
+ }
89971
+ }
89972
+ /** Inspect metadata only: consumer action contents and auxiliary files are never read. */
89973
+ function inspectSetupVerificationActionPath(root) {
89974
+ for (const parent of setup_verification_action_1.SETUP_VERIFICATION_ACTION_PARENTS) {
89975
+ const info = entry((0, node_path_1.join)(root, parent));
89976
+ if (!info)
89977
+ return 'create';
89978
+ if (!info.isDirectory() || info.isSymbolicLink())
89979
+ throw unsafe();
89980
+ }
89981
+ const info = entry((0, node_path_1.join)(root, setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH));
89982
+ if (!info)
89983
+ return 'create';
89984
+ if (!info.isFile() || info.isSymbolicLink())
89985
+ throw unsafe();
89986
+ return 'preserve';
89987
+ }
89988
+ /** Resolve the package-controlled starter, independently of workflow test overrides. */
89989
+ function readSetupVerificationActionStarter() {
89990
+ return fs.readFileSync((0, node_path_1.join)(__dirname, '..', '..', 'setup/actions/copilot-verification-setup/action.yml'), 'utf8');
89991
+ }
89992
+ /** Exclusive creation cannot truncate a file that wins the Apply race. */
89993
+ function createSetupVerificationAction(root, expected) {
89994
+ const state = inspectSetupVerificationActionPath(root);
89995
+ if (expected && expected !== state)
89996
+ throw stale();
89997
+ if (state === 'preserve')
89998
+ return { copied: 0, skipped: 1 };
89999
+ const content = readSetupVerificationActionStarter();
90000
+ const absoluteRoot = fs.realpathSync(root);
90001
+ const previousDirectory = fs.realpathSync('.');
90002
+ // Node has no portable openat. Pin each validated directory as the OS cwd,
90003
+ // then use only single-component relative operations. On POSIX this retains
90004
+ // the directory even if renamed; Windows locks the current directory.
90005
+ // This critical section is synchronous: never await or invoke user callbacks
90006
+ // here. The installer owns this main-thread section and always restores cwd.
90007
+ try {
90008
+ enterPinnedDirectory(absoluteRoot);
90009
+ for (const segment of ['.github', 'actions', 'copilot-verification-setup']) {
90010
+ try {
90011
+ fs.mkdirSync(segment);
90012
+ }
90013
+ catch (error) {
90014
+ if (error.code !== 'EEXIST')
90015
+ throw error;
90016
+ }
90017
+ enterPinnedDirectory(segment);
90018
+ }
90019
+ // Detect a relocated route before creation as well as after writing. A
90020
+ // replacement after this check cannot redirect the cwd-relative open.
90021
+ inspectSetupVerificationActionPath(absoluteRoot);
90022
+ writeStarterInPinnedDirectory(absoluteRoot, content);
90023
+ }
90024
+ finally {
90025
+ process.chdir(previousDirectory);
90026
+ }
90027
+ return { copied: 1, skipped: 0 };
90028
+ }
90029
+ function enterPinnedDirectory(path) {
90030
+ let descriptor;
90031
+ try {
90032
+ descriptor = fs.openSync(path, directoryFlags);
90033
+ }
90034
+ catch (error) {
90035
+ if (['ELOOP', 'ENOTDIR'].includes(error.code))
90036
+ throw unsafe();
90037
+ throw error;
90038
+ }
90039
+ try {
90040
+ // Keep the directory handle open until cwd is pinned, preventing inode reuse.
90041
+ const bound = fs.fstatSync(descriptor, { bigint: true });
90042
+ const observed = fs.lstatSync(path, { bigint: true });
90043
+ if (!bound.isDirectory() || !observed.isDirectory() || observed.isSymbolicLink())
90044
+ throw unsafe();
90045
+ if (!sameDirectory(bound, observed))
90046
+ throw stale();
90047
+ process.chdir(path);
90048
+ if (!sameDirectory(bound, fs.lstatSync('.', { bigint: true })))
90049
+ throw stale();
90050
+ }
90051
+ finally {
90052
+ fs.closeSync(descriptor);
90053
+ }
90054
+ }
90055
+ function writeStarterInPinnedDirectory(root, content) {
90056
+ const destination = 'action.yml';
90057
+ let descriptor;
90058
+ try {
90059
+ descriptor = fs.openSync(destination, 'wx', 0o644);
90060
+ }
90061
+ catch (error) {
90062
+ if (error.code === 'EEXIST')
90063
+ throw stale();
90064
+ throw error;
90065
+ }
90066
+ let created;
90067
+ try {
90068
+ try {
90069
+ created = fs.fstatSync(descriptor, { bigint: true });
90070
+ fs.writeFileSync(descriptor, content, 'utf8');
90071
+ if (inspectSetupVerificationActionPath(root) !== 'preserve')
90072
+ throw stale();
90073
+ if (!sameDirectory(fs.lstatSync('.', { bigint: true }), fs.lstatSync((0, node_path_1.join)(root, setup_verification_action_1.SETUP_VERIFICATION_ACTION_PARENTS[2]), { bigint: true })))
90074
+ throw stale();
90075
+ }
90076
+ finally {
90077
+ fs.closeSync(descriptor);
90078
+ }
90079
+ }
90080
+ catch (error) {
90081
+ // Remove only our incomplete file, never a concurrent replacement.
90082
+ try {
90083
+ const current = entry(destination);
90084
+ if (created && current?.dev === created.dev && current.ino === created.ino)
90085
+ fs.unlinkSync(destination);
90086
+ }
90087
+ catch { /* Preserve the original failure; an incomplete asset needs inspection. */ }
90088
+ throw error;
90089
+ }
90090
+ }
90091
+
90092
+
88408
90093
  /***/ }),
88409
90094
 
88410
90095
  /***/ 5729:
@@ -88434,6 +90119,7 @@ class SetupWorkspaceMutationAdapter {
88434
90119
  updateExistingWorkflows: selection?.updateExistingWorkflows,
88435
90120
  approvedWorkflowFiles: selection?.approvedWorkflowFiles,
88436
90121
  setupConfiguration: selection?.setupConfiguration,
90122
+ verificationActionState: selection.verificationActionState,
88437
90123
  });
88438
90124
  }
88439
90125
  hasValidToken(tokenOverride) {
@@ -88648,7 +90334,7 @@ const ALLOWED_VARIABLES = [
88648
90334
  * credentials or paths to local agent authentication stores.
88649
90335
  */
88650
90336
  function prepareUntrustedCommandEnvironment(source = process.env, platform = process.platform) {
88651
- const runtimeHome = (0, agent_private_install_root_1.createPrivateVerificationRuntimeRoot)();
90337
+ const runtimeHome = (0, node_fs_1.realpathSync)((0, agent_private_install_root_1.createPrivateVerificationRuntimeRoot)());
88652
90338
  const environment = { HOME: runtimeHome };
88653
90339
  for (const variable of ALLOWED_VARIABLES) {
88654
90340
  const value = source[variable];
@@ -88676,6 +90362,39 @@ function prepareUntrustedCommandEnvironment(source = process.env, platform = pro
88676
90362
  }
88677
90363
 
88678
90364
 
90365
+ /***/ }),
90366
+
90367
+ /***/ 20878:
90368
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
90369
+
90370
+ "use strict";
90371
+
90372
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
90373
+ exports.verificationExecutable = verificationExecutable;
90374
+ const node_fs_1 = __nccwpck_require__(87561);
90375
+ const node_path_1 = __nccwpck_require__(49411);
90376
+ /** @actions/exec resolves basenames against its own process PATH; native tools belong to the verifier PATH. */
90377
+ function verificationExecutable(program, environment, platform = process.platform) {
90378
+ const explicit = (0, node_path_1.isAbsolute)(program) || /[\\/]/u.test(program);
90379
+ const candidates = explicit ? [(0, node_path_1.resolve)(program)] : (environment.PATH ?? '').split(node_path_1.delimiter).filter(Boolean).map(directory => (0, node_path_1.resolve)((0, node_path_1.join)(directory, program)));
90380
+ const windowsExtensions = (environment.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';').filter(Boolean);
90381
+ const hasWindowsExtension = windowsExtensions.some(extension => program.toLowerCase().endsWith(extension.toLowerCase()));
90382
+ const extensions = platform === 'win32' && !hasWindowsExtension ? windowsExtensions : [''];
90383
+ for (const candidate of candidates)
90384
+ for (const extension of extensions) {
90385
+ const file = candidate + extension;
90386
+ try {
90387
+ if ((0, node_fs_1.statSync)(file).isFile()) {
90388
+ (0, node_fs_1.accessSync)(file, node_fs_1.constants.X_OK);
90389
+ return file;
90390
+ }
90391
+ }
90392
+ catch { /* Try only the next executable in the isolated PATH. */ }
90393
+ }
90394
+ throw new Error('Verification executable is unavailable in the isolated PATH.');
90395
+ }
90396
+
90397
+
88679
90398
  /***/ }),
88680
90399
 
88681
90400
  /***/ 91053:
@@ -88802,6 +90521,267 @@ function checkRuntime(requirement, environment, run, platform, job) {
88802
90521
  }
88803
90522
 
88804
90523
 
90524
+ /***/ }),
90525
+
90526
+ /***/ 23358:
90527
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
90528
+
90529
+ "use strict";
90530
+
90531
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
90532
+ exports.applyVerificationSetupResult = applyVerificationSetupResult;
90533
+ const node_fs_1 = __nccwpck_require__(87561);
90534
+ const node_path_1 = __nccwpck_require__(49411);
90535
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
90536
+ function contained(root, path) {
90537
+ const remainder = (0, node_path_1.relative)(root, path);
90538
+ return remainder === '' || (remainder !== '..' && !remainder.startsWith(`..${node_path_1.sep}`) && !(0, node_path_1.isAbsolute)(remainder));
90539
+ }
90540
+ /** Accept only existing contained directories, checking both lexical paths and symlink targets. */
90541
+ function approvedDirectory(value, roots) {
90542
+ if (!(0, node_path_1.isAbsolute)(value) || value.includes(node_path_1.delimiter) || value.split(/[\\/]/u).includes('..')
90543
+ || !roots.some(root => contained(root, value)))
90544
+ throw new verification_setup_policy_1.VerificationSetupError('result-invalid');
90545
+ const actual = (0, node_fs_1.realpathSync)(value);
90546
+ if (!roots.some(root => contained(root, actual)) || !(0, node_fs_1.lstatSync)(actual).isDirectory())
90547
+ throw new verification_setup_policy_1.VerificationSetupError('result-invalid');
90548
+ return actual;
90549
+ }
90550
+ function applyVerificationSetupResult(file, environment, roots) {
90551
+ let descriptor;
90552
+ try {
90553
+ let before;
90554
+ try {
90555
+ before = (0, node_fs_1.lstatSync)(file, { bigint: true });
90556
+ }
90557
+ catch (error) {
90558
+ if (error.code === 'ENOENT')
90559
+ return;
90560
+ throw error;
90561
+ }
90562
+ if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n || before.size > BigInt(verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.resultBytes))
90563
+ throw new Error();
90564
+ descriptor = (0, node_fs_1.openSync)(file, node_fs_1.constants.O_RDONLY | (node_fs_1.constants.O_NOFOLLOW ?? 0));
90565
+ const opened = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
90566
+ if (!opened.isFile() || opened.nlink !== 1n || opened.dev !== before.dev || opened.ino !== before.ino
90567
+ || opened.size !== before.size || opened.mtimeNs !== before.mtimeNs)
90568
+ throw new Error();
90569
+ const bytes = Buffer.alloc(verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.resultBytes + 1);
90570
+ const size = (0, node_fs_1.readSync)(descriptor, bytes, 0, bytes.length, 0);
90571
+ if (size > verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.resultBytes)
90572
+ throw new Error();
90573
+ const after = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
90574
+ if (after.size !== opened.size || after.mtimeNs !== opened.mtimeNs)
90575
+ throw new Error();
90576
+ const result = (0, verification_setup_policy_1.parseVerificationSetupResult)(JSON.parse(bytes.subarray(0, size).toString('utf8')));
90577
+ const paths = result.path.map(value => approvedDirectory(value, roots));
90578
+ const javaHome = result.javaHome ? approvedDirectory(result.javaHome, roots) : undefined;
90579
+ if (paths.length)
90580
+ environment.PATH = [...paths, ...(environment.PATH ? [environment.PATH] : [])].join(node_path_1.delimiter);
90581
+ if (javaHome)
90582
+ environment.JAVA_HOME = javaHome;
90583
+ }
90584
+ catch {
90585
+ throw new verification_setup_policy_1.VerificationSetupError('result-invalid');
90586
+ }
90587
+ finally {
90588
+ if (descriptor !== undefined)
90589
+ (0, node_fs_1.closeSync)(descriptor);
90590
+ }
90591
+ }
90592
+
90593
+
90594
+ /***/ }),
90595
+
90596
+ /***/ 11709:
90597
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
90598
+
90599
+ "use strict";
90600
+
90601
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
90602
+ exports.prepareRepositoryVerification = prepareRepositoryVerification;
90603
+ const verification_setup_snapshot_1 = __nccwpck_require__(62148);
90604
+ const native_verification_profiles_1 = __nccwpck_require__(22290);
90605
+ const node_fs_1 = __nccwpck_require__(87561);
90606
+ const node_path_1 = __nccwpck_require__(49411);
90607
+ const node_crypto_1 = __nccwpck_require__(6005);
90608
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
90609
+ const verification_setup_result_1 = __nccwpck_require__(23358);
90610
+ const logging_ports_1 = __nccwpck_require__(6152);
90611
+ const native_verification_protocol_1 = __nccwpck_require__(88709);
90612
+ const native_verification_staging_1 = __nccwpck_require__(63587);
90613
+ const native_verification_candidate_1 = __nccwpck_require__(18883);
90614
+ /** The runner executes YAML. This adapter pauses the admitted call stack at its verification boundary. */
90615
+ async function prepareRepositoryVerification(setup, environment) {
90616
+ if (setup.kind === 'disabled')
90617
+ return;
90618
+ if (setup.kind === 'blocked')
90619
+ throw new verification_setup_policy_1.VerificationSetupError(setup.reason, setup.sourceSha);
90620
+ const session = process.env.COPILOT_NATIVE_WORKER_SESSION;
90621
+ if (!session)
90622
+ throw new verification_setup_policy_1.VerificationSetupError('native-workflow-required', setup.sourceSha);
90623
+ let requestCreated = false;
90624
+ try {
90625
+ (0, native_verification_protocol_1.nativeSession)(session);
90626
+ const requests = (0, native_verification_protocol_1.readNativeRecord)(session, 'request-count.json')?.count ?? 0;
90627
+ if (requests >= verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.requests)
90628
+ throw new verification_setup_policy_1.VerificationSetupError('handoff-invalid');
90629
+ (0, native_verification_protocol_1.writeNativeRecord)(session, 'request-count.json', { count: requests + 1 });
90630
+ if ((0, node_fs_1.realpathSync)(process.cwd()) !== setup.workspace)
90631
+ throw new verification_setup_policy_1.VerificationSetupError('workspace-changed');
90632
+ (0, native_verification_profiles_1.registerNativeVerificationProfile)(session, environment.HOME);
90633
+ const identity = (0, native_verification_candidate_1.verificationCandidateIdentity)(setup.workspace, environment);
90634
+ (0, native_verification_staging_1.stageNativeVerificationAction)(setup, session);
90635
+ const id = (0, node_crypto_1.randomUUID)();
90636
+ (0, native_verification_protocol_1.writeNativeRecord)(session, 'request.json', { id, sourceSha: setup.sourceSha, digest: (0, verification_setup_snapshot_1.verificationSetupDigest)(setup), environment });
90637
+ requestCreated = true;
90638
+ (0, logging_ports_1.logInfo)(`Preparing repository verification (${verification_setup_policy_1.VERIFICATION_SETUP_PATH}; trusted source SHA: ${setup.sourceSha}).`);
90639
+ const deadline = Date.now() + verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.timeoutMs;
90640
+ let response;
90641
+ while (!(response = (0, native_verification_protocol_1.readNativeRecord)(session, `response-${id}.json`))) {
90642
+ if ((0, native_verification_protocol_1.readNativeRecord)(session, 'cancel.json'))
90643
+ throw new verification_setup_policy_1.VerificationSetupError('cancelled');
90644
+ if (Date.now() >= deadline)
90645
+ throw new verification_setup_policy_1.VerificationSetupError('timeout');
90646
+ await (0, native_verification_protocol_1.nativePause)(100);
90647
+ }
90648
+ if (response.id !== id || response.success !== true)
90649
+ throw new verification_setup_policy_1.VerificationSetupError('process-failed');
90650
+ if ((0, native_verification_candidate_1.verificationCandidateIdentity)(setup.workspace, environment) !== identity)
90651
+ throw new verification_setup_policy_1.VerificationSetupError('candidate-changed');
90652
+ if (typeof response.path !== 'string' || response.path.length > 16384 || response.javaHome !== undefined && typeof response.javaHome !== 'string')
90653
+ throw new verification_setup_policy_1.VerificationSetupError('result-invalid');
90654
+ const original = new Set((environment.PATH ?? '').split(node_path_1.delimiter));
90655
+ const previousProfiles = (0, native_verification_profiles_1.nativeVerificationProfilePaths)(session).filter(profile => profile !== environment.HOME);
90656
+ const fromPreviousProfile = (path) => previousProfiles.some(profile => {
90657
+ const part = (0, node_path_1.relative)(profile, path);
90658
+ return part === '' || part !== '..' && !part.startsWith(`..${node_path_1.sep}`) && !(0, node_path_1.isAbsolute)(part);
90659
+ });
90660
+ const additions = [...new Set(response.path.split(node_path_1.delimiter).filter(path => path && !original.has(path) && !fromPreviousProfile(path)))];
90661
+ const result = (0, node_path_1.join)(environment.HOME, 'native-setup-result.json');
90662
+ (0, node_fs_1.writeFileSync)(result, JSON.stringify({ schemaVersion: 1, path: additions,
90663
+ environment: response.javaHome && response.javaHome !== environment.JAVA_HOME ? { JAVA_HOME: response.javaHome } : {} }), { mode: 0o600, flag: 'wx' });
90664
+ (0, verification_setup_result_1.applyVerificationSetupResult)(result, environment, [setup.workspace, environment.HOME, ...(setup.toolRoot ? [setup.toolRoot] : [])]);
90665
+ (0, logging_ports_1.logInfo)('Repository setup completed; runtime preflight and verification may proceed.');
90666
+ }
90667
+ catch (error) {
90668
+ throw new verification_setup_policy_1.VerificationSetupError(error instanceof verification_setup_policy_1.VerificationSetupError ? error.reason : 'handoff-invalid', setup.sourceSha);
90669
+ }
90670
+ finally {
90671
+ if (requestCreated)
90672
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(session, 'request.json'), { force: true });
90673
+ }
90674
+ }
90675
+
90676
+
90677
+ /***/ }),
90678
+
90679
+ /***/ 62148:
90680
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
90681
+
90682
+ "use strict";
90683
+
90684
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
90685
+ exports.verificationSetupDigest = verificationSetupDigest;
90686
+ exports.captureVerificationSetup = captureVerificationSetup;
90687
+ exports.captureVerificationSetupAtCommit = captureVerificationSetupAtCommit;
90688
+ const node_path_1 = __nccwpck_require__(49411);
90689
+ const node_child_process_1 = __nccwpck_require__(17718);
90690
+ const node_crypto_1 = __nccwpck_require__(6005);
90691
+ const node_fs_1 = __nccwpck_require__(87561);
90692
+ const js_yaml_1 = __nccwpck_require__(783);
90693
+ const verification_setup_ports_1 = __nccwpck_require__(26509);
90694
+ const verification_setup_policy_1 = __nccwpck_require__(65326);
90695
+ const untrusted_command_environment_1 = __nccwpck_require__(2304);
90696
+ /** Only immutable Git objects are read. Errors remain deferred on non-verifying routes. */
90697
+ function verificationSetupDigest(setup) {
90698
+ return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(setup.files)).digest('hex');
90699
+ }
90700
+ function captureVerificationSetup(enabled, mainBranch, root = process.cwd()) {
90701
+ return capture(enabled, mainBranch, root);
90702
+ }
90703
+ /** Post steps use the already pinned commit from runner state, never a mutable branch ref. */
90704
+ function captureVerificationSetupAtCommit(commit, root = process.cwd(), gitExecutable) {
90705
+ return capture(true, '', root, commit, gitExecutable);
90706
+ }
90707
+ function capture(enabled, mainBranch, root, pinned, gitExecutable) {
90708
+ if (!enabled)
90709
+ return verification_setup_ports_1.DISABLED_VERIFICATION_SETUP;
90710
+ let sourceSha;
90711
+ let runtime;
90712
+ let snapshot;
90713
+ try {
90714
+ runtime = (0, untrusted_command_environment_1.prepareUntrustedCommandEnvironment)();
90715
+ const environment = runtime.environment;
90716
+ if (!pinned && (!/^[A-Za-z0-9][A-Za-z0-9._/-]{0,200}$/u.test(mainBranch) || mainBranch.includes('..')
90717
+ || mainBranch.includes('//') || mainBranch.endsWith('/') || mainBranch.endsWith('.lock')))
90718
+ throw new Error();
90719
+ if (gitExecutable !== undefined && !(0, node_path_1.isAbsolute)(gitExecutable))
90720
+ throw new Error();
90721
+ const workspace = (0, node_fs_1.realpathSync)(root);
90722
+ const git = (...args) => {
90723
+ const result = (0, node_child_process_1.spawnSync)(gitExecutable ?? 'git', ['--no-replace-objects', ...args], { cwd: workspace, env: environment,
90724
+ shell: false, windowsHide: true, timeout: 5000, maxBuffer: verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.snapshotBytes + 4096 });
90725
+ if (result.error || result.status !== 0)
90726
+ throw new Error();
90727
+ return result.stdout;
90728
+ };
90729
+ const sha = pinned ?? git('rev-parse', '--verify', `refs/remotes/origin/${mainBranch}^{commit}`).toString('utf8').trim();
90730
+ if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u.test(sha))
90731
+ throw new Error();
90732
+ sourceSha = sha;
90733
+ const entries = git('ls-tree', '-rz', sourceSha, '--', verification_setup_policy_1.VERIFICATION_SETUP_DIRECTORY).toString('utf8').split('\0').filter(Boolean);
90734
+ if (!entries.length || entries.length > verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.files)
90735
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90736
+ let total = 0;
90737
+ const files = entries.map(entry => {
90738
+ const match = /^(100644|100755) blob ([a-f0-9]{40}|[a-f0-9]{64})\t(.+)$/u.exec(entry);
90739
+ if (!match || !match[3].startsWith(`${verification_setup_policy_1.VERIFICATION_SETUP_DIRECTORY}/`))
90740
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90741
+ const path = match[3].slice(verification_setup_policy_1.VERIFICATION_SETUP_DIRECTORY.length + 1);
90742
+ if (!/^[A-Za-z0-9_./-]{1,200}$/u.test(path) || path.split('/').some(part => !part || part === '.' || part === '..' || part.endsWith('.') || /^(?:con|prn|aux|nul|com[0-9]|lpt[0-9])(?:\.|$)/iu.test(part)))
90743
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90744
+ const bytes = git('cat-file', 'blob', match[2]);
90745
+ total += bytes.length;
90746
+ const digest = (0, node_crypto_1.createHash)(match[2].length === 40 ? 'sha1' : 'sha256').update(`blob ${bytes.length}\0`).update(bytes).digest('hex');
90747
+ if (bytes.length > verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.scriptBytes || total > verification_setup_policy_1.VERIFICATION_SETUP_LIMITS.snapshotBytes || digest !== match[2])
90748
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90749
+ return Object.freeze({ path, base64: bytes.toString('base64'), executable: match[1] === '100755' });
90750
+ });
90751
+ const manifest = files.find(file => file.path === 'action.yml');
90752
+ if (!manifest)
90753
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90754
+ const bytes = Buffer.from(manifest.base64, 'base64');
90755
+ const text = bytes.toString('utf8');
90756
+ if (!bytes.length || !bytes.equals(Buffer.from(text)) || text.includes('\0'))
90757
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90758
+ let action;
90759
+ try {
90760
+ action = (0, js_yaml_1.load)(text);
90761
+ }
90762
+ catch {
90763
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90764
+ }
90765
+ if (action?.runs?.using !== 'composite' || !Array.isArray(action.runs.steps) || !action.runs.steps.length || action.runs.steps.length > 32)
90766
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90767
+ if (action.runs.steps.some(step => !step || typeof step !== 'object' || 'uses' in step && typeof step.uses === 'string' && step.uses.startsWith('./')))
90768
+ throw new verification_setup_policy_1.VerificationSetupError('helper-invalid');
90769
+ const toolRoot = environment.RUNNER_TOOL_CACHE ? (0, node_fs_1.realpathSync)(environment.RUNNER_TOOL_CACHE) : undefined;
90770
+ snapshot = Object.freeze({ kind: 'ready', files: Object.freeze(files), sourceSha, workspace, ...(toolRoot ? { toolRoot } : {}) });
90771
+ }
90772
+ catch (error) {
90773
+ snapshot = Object.freeze({ kind: 'blocked', reason: error instanceof verification_setup_policy_1.VerificationSetupError ? error.reason : 'source-unavailable', ...(sourceSha ? { sourceSha } : {}) });
90774
+ }
90775
+ try {
90776
+ runtime?.cleanup();
90777
+ }
90778
+ catch {
90779
+ snapshot = Object.freeze({ kind: 'blocked', reason: 'source-unavailable', ...(sourceSha ? { sourceSha } : {}) });
90780
+ }
90781
+ return snapshot;
90782
+ }
90783
+
90784
+
88805
90785
  /***/ }),
88806
90786
 
88807
90787
  /***/ 92540:
@@ -88959,26 +90939,64 @@ const logger_1 = __nccwpck_require__(91151);
88959
90939
  const issue_content_interface_1 = __nccwpck_require__(60608);
88960
90940
  const configuration_payload_policy_1 = __nccwpck_require__(58043);
88961
90941
  const application_error_1 = __nccwpck_require__(75999);
90942
+ const configuration_markers_1 = __nccwpck_require__(4586);
88962
90943
  class ConfigurationHandler extends issue_content_interface_1.IssueContentInterface {
88963
90944
  constructor() {
88964
90945
  super(...arguments);
90946
+ this.getContent = (description) => {
90947
+ const block = (0, configuration_markers_1.readConfigurationBlock)(description);
90948
+ return block.kind === 'present' ? block.content : undefined;
90949
+ };
90950
+ this.updateContent = (description, content) => {
90951
+ if (description === undefined || content === undefined)
90952
+ return undefined;
90953
+ const updated = (0, configuration_markers_1.writeConfigurationBlock)(description, content);
90954
+ if (updated === undefined)
90955
+ (0, logger_1.logError)('The content has a problem with open-close tags: stored configuration.');
90956
+ return updated;
90957
+ };
88965
90958
  this.update = async (query, context) => {
88966
90959
  const storedRaw = await this.internalGetter(query);
88967
90960
  return this.internalUpdate(query, (0, configuration_payload_policy_1.buildConfigurationPayload)(context, storedRaw));
88968
90961
  };
88969
90962
  this.get = async (query) => {
90963
+ let description;
90964
+ try {
90965
+ description = await this.issueDescriptionPort.getDescription(query.owner, query.repository, query.issueNumber, query.token);
90966
+ }
90967
+ catch (cause) {
90968
+ const semanticError = (0, application_error_1.toApplicationError)(cause, 'provider.unavailable', 'Unable to read issue configuration.');
90969
+ (0, logger_1.logError)(semanticError);
90970
+ throw semanticError;
90971
+ }
90972
+ const variables = { issueNumber: query.issueNumber, expectedVersion: config_1.CONFIG_SCHEMA_VERSION };
90973
+ let recovery = { id: 'stored-configuration-invalid', variables };
88970
90974
  try {
88971
- const description = await this.issueDescriptionPort.getDescription(query.owner, query.repository, query.issueNumber, query.token);
88972
90975
  const config = this.getContent(description);
88973
90976
  if (config === undefined) {
90977
+ if ((0, configuration_markers_1.readConfigurationBlock)(description).kind === 'invalid') {
90978
+ throw new Error('Stored configuration markers are inconsistent.');
90979
+ }
88974
90980
  return undefined;
88975
90981
  }
88976
- const branchConfig = (0, config_1.requireCurrentConfigurationPayload)(JSON.parse(config));
90982
+ const parsed = JSON.parse(config);
90983
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
90984
+ const version = parsed.schemaVersion;
90985
+ if (version === undefined) {
90986
+ recovery = { id: 'stored-configuration-schema-missing', variables };
90987
+ }
90988
+ else if (typeof version === 'number' && Number.isSafeInteger(version)
90989
+ && version >= 0 && version !== config_1.CONFIG_SCHEMA_VERSION) {
90990
+ recovery = { id: 'stored-configuration-schema-unsupported', variables: { ...variables, actualVersion: version } };
90991
+ }
90992
+ }
90993
+ const branchConfig = (0, config_1.requireCurrentConfigurationPayload)(parsed);
88977
90994
  return new config_1.Config(branchConfig);
88978
90995
  }
88979
- catch (error) {
88980
- (0, logger_1.logError)((0, application_error_1.toApplicationError)(error, 'configuration.invalid', 'Unable to read issue configuration.'));
88981
- throw error;
90996
+ catch (cause) {
90997
+ const semanticError = (0, application_error_1.toApplicationError)(cause, 'configuration.invalid', 'Stored issue/PR configuration is invalid.', { recovery });
90998
+ (0, logger_1.logError)(semanticError);
90999
+ throw semanticError;
88982
91000
  }
88983
91001
  };
88984
91002
  }
@@ -88992,6 +91010,96 @@ class ConfigurationHandler extends issue_content_interface_1.IssueContentInterfa
88992
91010
  exports.ConfigurationHandler = ConfigurationHandler;
88993
91011
 
88994
91012
 
91013
+ /***/ }),
91014
+
91015
+ /***/ 4586:
91016
+ /***/ ((__unused_webpack_module, exports) => {
91017
+
91018
+ "use strict";
91019
+
91020
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
91021
+ exports.CONFIGURATION_END = exports.CONFIGURATION_START = void 0;
91022
+ exports.readConfigurationBlock = readConfigurationBlock;
91023
+ exports.writeConfigurationBlock = writeConfigurationBlock;
91024
+ exports.CONFIGURATION_START = '<!-- copilot-configuration-start';
91025
+ exports.CONFIGURATION_END = 'copilot-configuration-end -->';
91026
+ /** Owned delimiters begin a line; ordinary mentions are not state. Complete legacy fenced records remain readable. */
91027
+ function readConfigurationBlock(description) {
91028
+ if (description === undefined)
91029
+ return { kind: 'absent' };
91030
+ let fence;
91031
+ let fencedMarker = false;
91032
+ let fencedStart;
91033
+ let nestedFencedStart = false;
91034
+ let start;
91035
+ let contentStart = 0;
91036
+ let block;
91037
+ let offset = 0;
91038
+ for (const line of description.match(/[^\n]*(?:\n|$)/gu) ?? []) {
91039
+ const text = line.replace(/\r?\n$/u, '');
91040
+ const starts = /^ {0,3}<!-- copilot-configuration-start(?:[ \t]|$)/u.test(text);
91041
+ const ends = /^ {0,3}copilot-configuration-end -->[ \t]*$/u.test(text);
91042
+ const boundary = /^ {0,3}(`{3,}|~{3,})(.*)$/u.exec(text);
91043
+ if (fence) {
91044
+ fencedMarker || (fencedMarker = starts || ends);
91045
+ if (starts) {
91046
+ if (fencedStart !== undefined)
91047
+ nestedFencedStart = true;
91048
+ else
91049
+ fencedStart = offset + text.indexOf(exports.CONFIGURATION_START);
91050
+ }
91051
+ const end = text.indexOf(exports.CONFIGURATION_END);
91052
+ if (fencedStart !== undefined && end >= 0 && !text.slice(end + exports.CONFIGURATION_END.length).trim()) {
91053
+ if (block || nestedFencedStart)
91054
+ return { kind: 'invalid' };
91055
+ block = { kind: 'present', start: fencedStart, end: offset + end + exports.CONFIGURATION_END.length,
91056
+ content: description.slice(fencedStart + exports.CONFIGURATION_START.length, offset + end) };
91057
+ fencedStart = undefined;
91058
+ }
91059
+ if (boundary && boundary[1][0] === fence[0] && boundary[1].length >= fence.length && !boundary[2].trim()) {
91060
+ fence = undefined;
91061
+ fencedMarker = false;
91062
+ fencedStart = undefined;
91063
+ nestedFencedStart = false;
91064
+ }
91065
+ }
91066
+ else if (start !== undefined || starts) {
91067
+ if (starts) {
91068
+ if (start !== undefined || block)
91069
+ return { kind: 'invalid' };
91070
+ start = offset + text.indexOf(exports.CONFIGURATION_START);
91071
+ contentStart = start + exports.CONFIGURATION_START.length;
91072
+ }
91073
+ const end = text.indexOf(exports.CONFIGURATION_END);
91074
+ if (end >= 0 && !text.slice(end + exports.CONFIGURATION_END.length).trim()) {
91075
+ block = { kind: 'present', start: start, end: offset + end + exports.CONFIGURATION_END.length,
91076
+ content: description.slice(contentStart, offset + end) };
91077
+ start = undefined;
91078
+ }
91079
+ }
91080
+ else if (ends)
91081
+ return { kind: 'invalid' };
91082
+ else if (boundary && (boundary[1][0] !== '`' || !boundary[2].includes('`')))
91083
+ fence = boundary[1];
91084
+ offset += line.length;
91085
+ }
91086
+ // A legacy block behind an unclosed fence is ambiguous: never silently discard its state.
91087
+ if (start !== undefined || fence && fencedMarker)
91088
+ return { kind: 'invalid' };
91089
+ return block ?? { kind: 'absent', ...(fence ? { closingFence: fence } : {}) };
91090
+ }
91091
+ function writeConfigurationBlock(description, content) {
91092
+ const block = readConfigurationBlock(description);
91093
+ if (block.kind === 'invalid')
91094
+ return undefined;
91095
+ const replacement = `${exports.CONFIGURATION_START}\n${content}\n${exports.CONFIGURATION_END}`;
91096
+ if (block.kind === 'present')
91097
+ return description.slice(0, block.start) + replacement + description.slice(block.end);
91098
+ // Closing an otherwise empty dangling example preserves its rendered text and keeps new state outside it.
91099
+ return `${description}\n\n${block.closingFence ? `${block.closingFence}\n\n` : ''}${replacement}`;
91100
+ }
91101
+
91102
+
88995
91103
  /***/ }),
88996
91104
 
88997
91105
  /***/ 58043:
@@ -89121,11 +91229,13 @@ function getBranchSyncConflictsPrompt(params) {
89121
91229
  "use strict";
89122
91230
 
89123
91231
  Object.defineProperty(exports, "__esModule", ({ value: true }));
91232
+ exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION = void 0;
89124
91233
  exports.getBugbotPrompt = getBugbotPrompt;
89125
91234
  /**
89126
91235
  * Prompt for Bugbot detection (detect potential problems on push).
89127
91236
  */
89128
91237
  const fill_1 = __nccwpck_require__(2559);
91238
+ exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION = 'Before returning a finding, try to disprove it against the exact reviewed source. Read effective repository configuration and inherited library/protocol defaults before inferring behavior from a missing command flag. Trace short-circuit guards, validation helpers and the actual caller/render path before claiming that an unsafe branch is reachable or that separate call sites coexist. Recompute arithmetic and check cited line numbers against the current file/diff. If your evidence refutes the alleged defect, withdraw the finding entirely; do not publish a contradictory or self-refuting report. These checks apply equally to low/info severity. Report a confirmed failure when those protections are absent; do not assume they exist.';
89129
91239
  const TEMPLATE = `You are analyzing the latest code changes for potential bugs and issues.
89130
91240
 
89131
91241
  Write every human-readable finding title, description, evidence, and suggestion in {{targetLocale}}. Preserve identifiers, code, symbols, paths, refs, commands, and URLs verbatim. Echo \`outputLocale\` exactly as \`{{targetLocale}}\`.
@@ -89161,6 +91271,8 @@ For every finding:
89161
91271
  - include the nearest stable \`symbol\` and a minimal exact \`codeSnippet\` when available so the finding can survive rebases, line movement, and file renames.
89162
91272
  - when a fix is a safe replacement of exactly the reported line range, include only the replacement text in \`suggestedCode\`; otherwise omit it.
89163
91273
 
91274
+ ${exports.BUGBOT_FINDING_GROUNDING_INSTRUCTION}
91275
+
89164
91276
  Return every finding field required by the response schema. Use null for file, line, endLine, severity, confidence, category, evidence, suggestion, symbol, codeSnippet, or suggestedCode when that value does not safely apply. Only include files outside the ignore list.
89165
91277
  {{previousBlock}}
89166
91278
 
@@ -90638,11 +92750,13 @@ const setup_approval_workflow_1 = __nccwpck_require__(9512);
90638
92750
  const setup_workflow_upgrade_1 = __nccwpck_require__(85493);
90639
92751
  const setup_installation_review_1 = __nccwpck_require__(23799);
90640
92752
  const repository_agent_guidance_policy_1 = __nccwpck_require__(67402);
92753
+ const setup_verification_action_1 = __nccwpck_require__(12471);
90641
92754
  /**
90642
92755
  * Ensure .github, .github/workflows and .github/ISSUE_TEMPLATE exist; create them if missing.
90643
92756
  * @param cwd - Directory (repo root)
90644
92757
  */
90645
92758
  function ensureGitHubDirs(cwd) {
92759
+ (0, setup_verification_action_1.inspectSetupVerificationActionPath)(cwd);
90646
92760
  const githubDir = path.join(cwd, '.github');
90647
92761
  const workflowsDir = path.join(cwd, '.github', 'workflows');
90648
92762
  const issueTemplateDir = path.join(cwd, '.github', 'ISSUE_TEMPLATE');
@@ -90675,6 +92789,7 @@ function copySetupFiles(cwd, setupDirOverride, features, options = {}) {
90675
92789
  const installationReview = options.setupConfiguration && (0, setup_installation_review_1.inspectSetupInstallation)(cwd, options.setupConfiguration, setupDir);
90676
92790
  if (installationReview?.blockers.length)
90677
92791
  throw new Error(installationReview.blockers.join(' '));
92792
+ const verificationAction = (0, setup_verification_action_1.createSetupVerificationAction)(cwd, options.verificationActionState);
90678
92793
  const preserveSourceGuidance = installationReview?.assets.some(asset => asset.path === repository_agent_guidance_policy_1.REPOSITORY_AGENT_GUIDE_PATH && asset.status === 'source-only');
90679
92794
  const sourceInstallation = installationReview?.assets.some(asset => asset.path.startsWith('.github/workflows/') && asset.status === 'source-only');
90680
92795
  const snapshotContent = options.setupConfiguration && (0, setup_installation_review_1.renderSetupRunnerSnapshot)(options.setupConfiguration);
@@ -90729,7 +92844,7 @@ function copySetupFiles(cwd, setupDirOverride, features, options = {}) {
90729
92844
  snapshot.copied++;
90730
92845
  }
90731
92846
  }
90732
- return [retired, workflows, approvalWorkflow, issueTemplates, pullRequestTemplate, guidance, snapshot].reduce((total, current) => ({
92847
+ return [verificationAction, retired, workflows, approvalWorkflow, issueTemplates, pullRequestTemplate, guidance, snapshot].reduce((total, current) => ({
90733
92848
  copied: total.copied + current.copied,
90734
92849
  skipped: total.skipped + current.skipped,
90735
92850
  }), { copied: 0, skipped: 0 });
@@ -90943,6 +93058,9 @@ const setup_workflow_upgrade_1 = __nccwpck_require__(85493);
90943
93058
  const setup_approval_workflow_1 = __nccwpck_require__(9512);
90944
93059
  const sensitive_text_1 = __nccwpck_require__(47122);
90945
93060
  const repository_agent_guidance_policy_1 = __nccwpck_require__(67402);
93061
+ const setup_verification_action_1 = __nccwpck_require__(33156);
93062
+ const setup_verification_action_2 = __nccwpck_require__(12471);
93063
+ const copilot_comment_workflow_1 = __nccwpck_require__(33430);
90946
93064
  exports.SETUP_RUNNER_SNAPSHOT = '.copilot/runner-profile.json';
90947
93065
  const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
90948
93066
  ? value : undefined;
@@ -90984,6 +93102,22 @@ function inspectSetupInstallation(root, configuration, setup = (0, node_path_1.j
90984
93102
  const jobs = [];
90985
93103
  const changes = [];
90986
93104
  const blockers = [];
93105
+ let action;
93106
+ try {
93107
+ action = (0, setup_verification_action_2.inspectSetupVerificationActionPath)(root);
93108
+ }
93109
+ catch (error) {
93110
+ action = 'blocked';
93111
+ blockers.push(error instanceof Error ? error.message : 'Verification setup path could not be inspected.');
93112
+ }
93113
+ const verificationSetup = { action, enabled: configuration.repository.verificationSetup ?? false,
93114
+ mainBranch: configuration.repository.mainBranch };
93115
+ assets.push({ path: setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH, enabled: verificationSetup.enabled,
93116
+ status: action === 'create' ? 'missing' : action === 'preserve' ? 'customized' : 'incompatible' });
93117
+ if (action === 'blocked')
93118
+ return { assets, jobs, changes, blockers, verificationSetup };
93119
+ if (action === 'create')
93120
+ changes.push({ path: setup_verification_action_1.SETUP_VERIFICATION_ACTION_PATH, before: null, after: (0, setup_verification_action_2.readSetupVerificationActionStarter)() });
90987
93121
  const addJobs = (file, content, retained) => {
90988
93122
  const documents = (0, js_yaml_1.loadAll)(content);
90989
93123
  if (documents.length !== 1)
@@ -90992,7 +93126,7 @@ function inspectSetupInstallation(root, configuration, setup = (0, node_path_1.j
90992
93126
  if (!parsedJobs)
90993
93127
  throw new Error('Workflow jobs are unavailable for review.');
90994
93128
  for (const [job, raw] of Object.entries(parsedJobs)) {
90995
- const runsOn = object(raw)?.['runs-on'];
93129
+ const runsOn = (0, copilot_comment_workflow_1.copilotCommentRunner)(object(raw));
90996
93130
  if (runsOn === undefined)
90997
93131
  continue; // reusable workflow calls have no runner
90998
93132
  jobs.push({ file, job, role: (0, setup_runner_policy_1.setupRunnerRole)(file, job) ?? 'validation',
@@ -91080,7 +93214,7 @@ function inspectSetupInstallation(root, configuration, setup = (0, node_path_1.j
91080
93214
  before: before === undefined ? null : (0, sensitive_text_1.redactSensitiveText)(before), after: (0, sensitive_text_1.redactSensitiveText)(after) });
91081
93215
  if (after !== undefined && before !== undefined && !compatibleSetupRunnerSnapshot(before))
91082
93216
  blockers.push('Runner snapshot is incompatible. Retain it or restore a supported version before replacing routing.');
91083
- return { assets, jobs, changes, blockers };
93217
+ return { assets, jobs, changes, blockers, verificationSetup };
91084
93218
  }
91085
93219
 
91086
93220
 
@@ -91099,6 +93233,7 @@ const js_yaml_1 = __nccwpck_require__(783);
91099
93233
  const node_util_1 = __nccwpck_require__(47261);
91100
93234
  const setup_runner_policy_1 = __nccwpck_require__(91027);
91101
93235
  const action_types_1 = __nccwpck_require__(19625);
93236
+ const copilot_comment_workflow_1 = __nccwpck_require__(33430);
91102
93237
  const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
91103
93238
  const document = (value) => {
91104
93239
  try {
@@ -91120,6 +93255,8 @@ const runner = (value) => labels(value) || !!object(value)
91120
93255
  && (object(value).labels === undefined || labels(object(value).labels));
91121
93256
  const copilotCommands = new Set(Object.values(action_types_1.ACTIONS));
91122
93257
  const callsRootAction = (jobs) => !!jobs && Object.values(jobs).some(job => {
93258
+ if (object(job)?.uses === copilot_comment_workflow_1.COPILOT_COMMENT_SELF_WORKFLOW)
93259
+ return true;
91123
93260
  const steps = object(job)?.steps;
91124
93261
  return Array.isArray(steps) && steps.some(step => {
91125
93262
  const invocation = object(step);
@@ -91182,6 +93319,32 @@ function renderSetupWorkflowUpgrade(template, existing, selection) {
91182
93319
  const templateJobs = object(document(template)?.jobs);
91183
93320
  if (!previousJobs || !templateJobs)
91184
93321
  throw new Error('Workflow jobs cannot be inspected; review the workflow separately.');
93322
+ if (Object.values(templateJobs).some(job => (0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(object(job)?.uses))) {
93323
+ const parsed = document(template);
93324
+ const jobs = object(parsed.jobs);
93325
+ let changed = false;
93326
+ for (const [name, value] of Object.entries(jobs)) {
93327
+ const job = object(value);
93328
+ if (!(0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(job.uses))
93329
+ throw new Error('Mixed comment workflow jobs require separate workflow review before setup.');
93330
+ const previousJob = object(previousJobs[name]);
93331
+ if (Array.isArray(previousJob?.steps) && previousJob.steps.some(raw => {
93332
+ const uses = object(raw)?.uses;
93333
+ return typeof uses !== 'string' || !(uses.startsWith('actions/checkout@')
93334
+ || /^vypdev\/copilot@[^\s]+$/u.test(uses) || uses === './.git/copilot-verification-setup');
93335
+ }))
93336
+ throw new Error('Custom comment job steps require migration to the reviewed repository verification setup action before switching to the reusable workflow. Review the workflow separately.');
93337
+ const retained = (0, setup_runner_policy_1.selectedSetupRunsOn)(selection?.runners, selection && (0, setup_runner_policy_1.setupRunnerRole)(selection.file, name))
93338
+ ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(previousJob) ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(job);
93339
+ if (!runner(retained))
93340
+ throw new Error('Existing runner selection is invalid; review the workflow separately.');
93341
+ if (JSON.stringify(retained).includes('${{') && existing !== template)
93342
+ throw new Error('Dynamic runner selection requires separate workflow review before setup.');
93343
+ changed || (changed = !(0, node_util_1.isDeepStrictEqual)(retained, (0, copilot_comment_workflow_1.copilotCommentRunner)(job)));
93344
+ job.with = { ...object(job.with), 'runs-on': JSON.stringify(retained) };
93345
+ }
93346
+ return changed ? (0, js_yaml_1.dump)(parsed, { noRefs: true, lineWidth: -1 }) : template;
93347
+ }
91185
93348
  const lines = template.split('\n');
91186
93349
  let job = '';
91187
93350
  let insideJobs = false;
@@ -91557,6 +93720,14 @@ module.exports = require("node:stream");
91557
93720
 
91558
93721
  /***/ }),
91559
93722
 
93723
+ /***/ 76915:
93724
+ /***/ ((module) => {
93725
+
93726
+ "use strict";
93727
+ module.exports = require("node:string_decoder");
93728
+
93729
+ /***/ }),
93730
+
91560
93731
  /***/ 31764:
91561
93732
  /***/ ((module) => {
91562
93733