@vypdev/copilot 3.9.0 → 3.9.2

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.
@@ -38002,6 +38002,23 @@ exports.TITLE = void 0;
38002
38002
  exports.TITLE = 'Copilot';
38003
38003
 
38004
38004
 
38005
+ /***/ }),
38006
+
38007
+ /***/ 2396:
38008
+ /***/ ((__unused_webpack_module, exports) => {
38009
+
38010
+ "use strict";
38011
+
38012
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
38013
+ exports.SETUP_DOCUMENTATION = void 0;
38014
+ /** Public, source-controlled navigation. Never attach session, repository or credential data. */
38015
+ exports.SETUP_DOCUMENTATION = {
38016
+ tutorial: 'https://docs.page/vypdev/copilot/setup-web',
38017
+ firstWorkflow: 'https://docs.page/vypdev/copilot/first-workflow',
38018
+ recovery: 'https://docs.page/vypdev/copilot/security-operations/operations/troubleshooting',
38019
+ };
38020
+
38021
+
38005
38022
  /***/ }),
38006
38023
 
38007
38024
  /***/ 75999:
@@ -39201,6 +39218,11 @@ const SPANISH_CONTENT = Object.freeze({
39201
39218
  action: 'Corrige la entrada y reinténtalo.',
39202
39219
  retainedState: UNCHANGED_STATE_ES,
39203
39220
  }),
39221
+ 'validation.evidence-unavailable': Object.freeze({
39222
+ impact: 'No se evaluó el progreso porque GitHub omitió un patch necesario.',
39223
+ action: 'Inspecciona manualmente la comparación entre los commits base y head exactos o divide el trabajo en cambios revisados más pequeños con patches completos antes de otra evaluación. Reintentar los mismos commits no recuperará la evidencia omitida.',
39224
+ retainedState: 'Se conservaron las etiquetas de progreso y las evaluaciones publicadas; no se realizó ninguna evaluación del modelo.',
39225
+ }),
39204
39226
  'validation.evidence-too-large': Object.freeze({
39205
39227
  impact: 'No se pudo evaluar el progreso dentro de los límites fijos de evidencia.',
39206
39228
  action: 'Reduce el tamaño de la comparación o divide el trabajo en cambios revisados más pequeños antes de iniciar otra evaluación.',
@@ -45857,6 +45879,34 @@ function verifiedReadinessLink(snapshot, number) {
45857
45879
  }
45858
45880
 
45859
45881
 
45882
+ /***/ }),
45883
+
45884
+ /***/ 59756:
45885
+ /***/ ((__unused_webpack_module, exports) => {
45886
+
45887
+ "use strict";
45888
+
45889
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
45890
+ exports.hasConventionalPullRequestTitle = hasConventionalPullRequestTitle;
45891
+ exports.generatedPullRequestTitle = generatedPullRequestTitle;
45892
+ /** Recognizes the conventional header shape; the consumer's CI owns its allowed types and subject rules. */
45893
+ function hasConventionalPullRequestTitle(title) {
45894
+ return !title.includes('\n') && !title.includes('\r')
45895
+ && /^\p{L}[\p{L}\p{N}_-]*(?:\([^()\r\n]+\))?!?: +\S[^\r\n]*$/u.test(title);
45896
+ }
45897
+ function generatedPullRequestTitle(sourceTitle, sanitizedSubject, issueNumber, labels) {
45898
+ if (hasConventionalPullRequestTitle(sourceTitle))
45899
+ return sourceTitle;
45900
+ const type = labels.isHotfix || labels.isBugfix || labels.isBug ? 'fix'
45901
+ : labels.isFeature || labels.isEnhancement ? 'feat'
45902
+ : labels.isDocs || labels.isDocumentation ? 'docs' : 'chore';
45903
+ const prefix = `${type}: `;
45904
+ const suffix = ` (#${issueNumber})`;
45905
+ const subject = (sanitizedSubject || 'Update linked issue').slice(0, 256 - prefix.length - suffix.length).trimEnd();
45906
+ return `${prefix}${subject}${suffix}`;
45907
+ }
45908
+
45909
+
45860
45910
  /***/ }),
45861
45911
 
45862
45912
  /***/ 39410:
@@ -46048,6 +46098,12 @@ Do not add the \`${profile.deployment.launcherLabel}\` label, dispatch a deploym
46048
46098
 
46049
46099
  Never expose credentials, tokens, private keys, or other secrets in issues, commits, pull requests, logs, or diagnostic comments.
46050
46100
 
46101
+ ## Repository verification prerequisites
46102
+
46103
+ The setup runner profile selects placement; it does not install the project's language runtimes. An operator must provision the project's required runtimes and dependencies in every job that runs file-changing or branch-sync verification, before the Copilot step. A separate application CI job does not prepare this job.
46104
+
46105
+ 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).
46106
+
46051
46107
  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).
46052
46108
  `;
46053
46109
  }
@@ -50154,13 +50210,16 @@ function validateDiscoveredProjectStatuses(configuration, discovery) {
50154
50210
  Object.defineProperty(exports, "__esModule", ({ value: true }));
50155
50211
  exports.setupQuestionDocumentation = setupQuestionDocumentation;
50156
50212
  const docs = {
50157
- features: { title: 'Copilot features and workflow triggers', url: 'https://docs.page/vypdev/copilot/features' },
50158
- issueWorkflows: { title: 'Copilot issue workflow setup', url: 'https://docs.page/vypdev/copilot/issues/workflow-setup' },
50213
+ features: { title: 'Choose a Copilot goal', url: 'https://docs.page/vypdev/copilot/guides' },
50214
+ issueWorkflows: { title: 'Select issue kinds and forms', url: 'https://docs.page/vypdev/copilot/issues/configurable-workflows' },
50215
+ issuesGuide: { title: 'Manage issues and branches', url: 'https://docs.page/vypdev/copilot/guides/issues-and-branches' },
50216
+ reviewGuide: { title: 'Review PRs and resolve findings', url: 'https://docs.page/vypdev/copilot/guides/review-pull-requests' },
50217
+ botGuide: { title: 'Work with the bot', url: 'https://docs.page/vypdev/copilot/guides/work-with-the-bot' },
50218
+ releaseGuide: { title: 'Release and hotfix guide', url: 'https://docs.page/vypdev/copilot/guides/releases-and-hotfixes' },
50159
50219
  branchManagement: { title: 'Issue branch management', url: 'https://docs.page/vypdev/copilot/issues/branch-management' },
50160
50220
  preBranchSdd: { title: 'Pre-branch design documents', url: 'https://docs.page/vypdev/copilot/issues/pre-branch-sdds' },
50161
50221
  issueLifecycle: { title: 'Issue notifications and automatic closure', url: 'https://docs.page/vypdev/copilot/issues/notifications-and-auto-close' },
50162
50222
  assignments: { title: 'Assignees and GitHub Projects', url: 'https://docs.page/vypdev/copilot/issues/assignees-and-projects' },
50163
- pullRequestWorkflows: { title: 'Pull-request workflow setup', url: 'https://docs.page/vypdev/copilot/pull-requests/workflow-setup' },
50164
50223
  pullRequestDescription: { title: 'AI pull-request descriptions', url: 'https://docs.page/vypdev/copilot/pull-requests/ai-description' },
50165
50224
  repositoryGuidance: { title: 'Repository guidance for agents', url: 'https://docs.page/vypdev/copilot/agents/repository-collaboration' },
50166
50225
  runtime: { title: 'Agent runtime selection', url: 'https://docs.page/vypdev/copilot/agents/runtime-selection' },
@@ -50175,7 +50234,7 @@ const docs = {
50175
50234
  projects: { title: 'Assignees and GitHub Projects', url: 'https://docs.page/vypdev/copilot/issues/assignees-and-projects' },
50176
50235
  githubProjects: { title: 'GitHub: About Projects', url: 'https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects' },
50177
50236
  githubStatus: { title: 'GitHub: About single-select fields', url: 'https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-single-select-fields' },
50178
- provisioning: { title: 'Copilot setup and provisioning', url: 'https://docs.page/vypdev/copilot/how-to-use' },
50237
+ provisioning: { title: 'Set up with the web assistant', url: 'https://docs.page/vypdev/copilot/setup-web' },
50179
50238
  storage: { title: 'GitHub Actions Secrets and Variables', url: 'https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets' },
50180
50239
  };
50181
50240
  /** Links are selected from source-controlled constants, never derived from answers or remote text. */
@@ -50185,10 +50244,14 @@ function setupQuestionDocumentation(question) {
50185
50244
  return { title: 'Runner profiles', url: 'https://docs.page/vypdev/copilot/configuration#runner-profiles' };
50186
50245
  if (id === 'issueWorkflows.enabled')
50187
50246
  return docs.issueWorkflows;
50188
- if (id === 'features.issues')
50189
- return docs.issueWorkflows;
50247
+ if (id === 'features.issues' || id === 'features.commits')
50248
+ return docs.issuesGuide;
50190
50249
  if (id === 'features.pullRequests')
50191
- return docs.pullRequestWorkflows;
50250
+ return docs.reviewGuide;
50251
+ if (id === 'features.issueComments' || id === 'features.pullRequestComments')
50252
+ return docs.botGuide;
50253
+ if (id === 'features.release' || id === 'features.hotfix')
50254
+ return docs.releaseGuide;
50192
50255
  if (id === 'repository.issueManagedBranches' || /^repository\.(feature|bugfix|hotfix|release|docs|chore)Tree$/u.test(id))
50193
50256
  return docs.branchManagement;
50194
50257
  if (id === 'repository.preBranchSdd')
@@ -53043,6 +53106,87 @@ function projectCurrentNativeStatus(status, facts) {
53043
53106
  }
53044
53107
 
53045
53108
 
53109
+ /***/ }),
53110
+
53111
+ /***/ 89347:
53112
+ /***/ ((__unused_webpack_module, exports) => {
53113
+
53114
+ "use strict";
53115
+
53116
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
53117
+ exports.VerificationPrerequisiteError = exports.VERIFICATION_RUNTIME_SPECS = exports.VERIFICATION_RUNTIME_HELP = exports.VERIFICATION_RUNTIME_MANIFEST = void 0;
53118
+ exports.parseVerificationRuntimeManifest = parseVerificationRuntimeManifest;
53119
+ exports.verificationRuntimeVersion = verificationRuntimeVersion;
53120
+ exports.verificationRuntimeMatches = verificationRuntimeMatches;
53121
+ exports.VERIFICATION_RUNTIME_MANIFEST = '.copilot/verification-prerequisites.json';
53122
+ exports.VERIFICATION_RUNTIME_HELP = 'https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites';
53123
+ exports.VERIFICATION_RUNTIME_SPECS = {
53124
+ java: { label: 'Java', program: 'java', args: ['-version'] },
53125
+ node: { label: 'Node.js', program: 'node', args: ['--version'] },
53126
+ pnpm: { label: 'pnpm', program: 'pnpm', args: ['--version'] },
53127
+ python: { label: 'Python', program: 'python3', args: ['--version'] },
53128
+ go: { label: 'Go', program: 'go', args: ['version'] },
53129
+ dotnet: { label: '.NET SDK', program: 'dotnet', args: ['--version'] },
53130
+ ruby: { label: 'Ruby', program: 'ruby', args: ['--version'] },
53131
+ rust: { label: 'Rust', program: 'rustc', args: ['--version'] },
53132
+ };
53133
+ const VERSION_PREFIX = /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,2}$/u;
53134
+ /** Only reviewed, closed runtime/version facts enter user-visible diagnostics. Raw tool output never does. */
53135
+ class VerificationPrerequisiteError extends Error {
53136
+ constructor(reason, requirement, observed, job) {
53137
+ const jobLabel = job && /^[A-Za-z_][A-Za-z0-9_-]{0,99}$/u.test(job) ? ` in job ${job}` : ' in this job';
53138
+ const runtime = requirement && Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, requirement.runtime)
53139
+ ? exports.VERIFICATION_RUNTIME_SPECS[requirement.runtime].label : 'Required runtime';
53140
+ const version = requirement && VERSION_PREFIX.test(requirement.version) ? requirement.version : 'declared version';
53141
+ const actual = observed && /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,3}$/u.test(observed) ? observed : 'unavailable';
53142
+ const cause = reason === 'manifest-invalid' ? `${exports.VERIFICATION_RUNTIME_MANIFEST} is invalid or unsafe`
53143
+ : reason === 'version-mismatch' ? `${runtime} ${version} is required; observed ${actual}`
53144
+ : reason === 'unreadable-version' ? `${runtime} ${version} could not be verified`
53145
+ : `${runtime} ${version} is unavailable`;
53146
+ const action = reason === 'manifest-invalid' ? 'Correct the reviewed runtime declaration.'
53147
+ : `Provision the declared runtime in the same job before Copilot, then retry.${requirement?.runtime === 'java' ? ' For Java, configure actions/setup-java or a managed JAVA_HOME.' : ''}`;
53148
+ super(`Repository verification is blocked${jobLabel}: ${cause}. ${action} The repository verification command was not run. Help: ${exports.VERIFICATION_RUNTIME_HELP}`);
53149
+ this.name = 'VerificationPrerequisiteError';
53150
+ }
53151
+ }
53152
+ exports.VerificationPrerequisiteError = VerificationPrerequisiteError;
53153
+ function parseVerificationRuntimeManifest(value) {
53154
+ if (!value || typeof value !== 'object' || Array.isArray(value))
53155
+ throw new VerificationPrerequisiteError('manifest-invalid');
53156
+ const object = value;
53157
+ if (object.schemaVersion !== 1 || Object.keys(object).some(key => !['schemaVersion', 'runtimes'].includes(key))
53158
+ || !object.runtimes || typeof object.runtimes !== 'object' || Array.isArray(object.runtimes)) {
53159
+ throw new VerificationPrerequisiteError('manifest-invalid');
53160
+ }
53161
+ const runtimes = object.runtimes;
53162
+ if (Object.keys(runtimes).length > 8)
53163
+ throw new VerificationPrerequisiteError('manifest-invalid');
53164
+ return Object.entries(runtimes).map(([runtime, version]) => {
53165
+ if (!Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, runtime) || typeof version !== 'string' || !VERSION_PREFIX.test(version)) {
53166
+ throw new VerificationPrerequisiteError('manifest-invalid');
53167
+ }
53168
+ return Object.freeze({ runtime: runtime, version });
53169
+ });
53170
+ }
53171
+ function verificationRuntimeVersion(runtime, output) {
53172
+ const patterns = {
53173
+ java: /^(?:openjdk|java) (?:version )?["']?(\d+(?:\.\d+){0,3})/imu,
53174
+ node: /^v(\d+\.\d+\.\d+)/mu,
53175
+ pnpm: /^(\d+\.\d+\.\d+)/mu,
53176
+ python: /^Python (\d+\.\d+\.\d+)/mu,
53177
+ go: /^go version go(\d+\.\d+(?:\.\d+)?)/mu,
53178
+ dotnet: /^(\d+\.\d+\.\d+)/mu,
53179
+ ruby: /^ruby (\d+\.\d+\.\d+)/mu,
53180
+ rust: /^rustc (\d+\.\d+\.\d+)/mu,
53181
+ };
53182
+ const version = patterns[runtime].exec(output)?.[1];
53183
+ return runtime === 'java' && version?.startsWith('1.') ? version.slice(2) : version;
53184
+ }
53185
+ function verificationRuntimeMatches(required, observed) {
53186
+ return observed === required || observed.startsWith(`${required}.`);
53187
+ }
53188
+
53189
+
53046
53190
  /***/ }),
53047
53191
 
53048
53192
  /***/ 43193:
@@ -57138,7 +57282,7 @@ class SyncBranchUseCase {
57138
57282
  const commands = (0, verify_command_policy_1.limitVerifyCommands)([...context.verifyCommands]);
57139
57283
  if (commands.length === verify_command_policy_1.MAX_VERIFY_COMMANDS)
57140
57284
  (0, logging_ports_1.logInfo)(`Branch sync verification is capped at ${verify_command_policy_1.MAX_VERIFY_COMMANDS} commands.`);
57141
- const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true }));
57285
+ const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
57142
57286
  if (!verification.success) {
57143
57287
  return {
57144
57288
  commandCount: commands.length,
@@ -65653,7 +65797,7 @@ async function runVerification(context, gitCommitPort) {
65653
65797
  if (verifyCommands.length === 0)
65654
65798
  return undefined;
65655
65799
  (0, logging_ports_1.logInfo)(`Running ${verifyCommands.length} verify ${verifyCommands.length === 1 ? 'command' : 'commands'}...`);
65656
- const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true }));
65800
+ const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
65657
65801
  return verify.success
65658
65802
  ? undefined
65659
65803
  : verify.error ?? `Verify command failed: ${verify.failedCommand ?? "unknown"}.`;
@@ -67876,6 +68020,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
67876
68020
  exports.runVerifyCommands = runVerifyCommands;
67877
68021
  const logging_ports_1 = __nccwpck_require__(6152);
67878
68022
  const verify_command_policy_1 = __nccwpck_require__(96031);
68023
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
67879
68024
  async function runVerifyCommands(commands, execute) {
67880
68025
  for (const command of commands) {
67881
68026
  const result = await executeVerifyCommand(command, execute);
@@ -67894,7 +68039,11 @@ async function executeVerifyCommand(command, execute) {
67894
68039
  ? { success: true }
67895
68040
  : { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
67896
68041
  }
67897
- catch {
68042
+ catch (error) {
68043
+ if (error instanceof verification_runtime_policy_1.VerificationPrerequisiteError) {
68044
+ return { success: false, failedCommand: formatCommandForDiagnostics(parsed),
68045
+ error: `${error.message} Verification command: ${formatCommandForDiagnostics(parsed)}.` };
68046
+ }
67898
68047
  (0, logging_ports_1.logError)('Verify command failed.');
67899
68048
  return { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
67900
68049
  }
@@ -70076,6 +70225,7 @@ exports.titleUpdateFailure = titleUpdateFailure;
70076
70225
  const result_1 = __nccwpck_require__(73817);
70077
70226
  const application_error_1 = __nccwpck_require__(75999);
70078
70227
  const positive_integer_policy_1 = __nccwpck_require__(19879);
70228
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
70079
70229
  function projectUpdateTitleContext(source) {
70080
70230
  if (source.isIssue) {
70081
70231
  return Object.freeze({
@@ -70126,19 +70276,27 @@ async function runPullRequestTitleUpdate(param, taskId, issueRepository) {
70126
70276
  if (!linkedIssueNumber || linkedIssueNumber === param.pullRequestNumber) {
70127
70277
  return [skippedResult(taskId)];
70128
70278
  }
70279
+ const currentTitle = await issueRepository.getTitle(param.pullRequestNumber);
70280
+ if (currentTitle === undefined) {
70281
+ return [new result_1.Result({ id: taskId, success: false, executed: true,
70282
+ steps: ['The current pull request title could not be read. No title change was attempted.'],
70283
+ errors: [new application_error_1.ApplicationError('provider.unavailable', 'Unable to read the current pull request title.')] })];
70284
+ }
70285
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(currentTitle))
70286
+ return [skippedResult(taskId)];
70129
70287
  const issueTitle = await issueRepository.getTitle(linkedIssueNumber);
70130
70288
  if (issueTitle === undefined) {
70131
70289
  return [new result_1.Result({ id: taskId, success: false, executed: true, steps: ['Tried to update title, but there was a problem.'] })];
70132
70290
  }
70133
70291
  const title = await issueRepository.updatePullRequestTitle({
70134
- pullRequestTitle: param.pullRequestTitle,
70292
+ pullRequestTitle: currentTitle,
70135
70293
  issueTitle,
70136
70294
  issueNumber: linkedIssueNumber,
70137
70295
  pullRequestNumber: param.pullRequestNumber,
70138
70296
  labelFacts: param.labelFacts,
70139
70297
  });
70140
70298
  return title
70141
- ? [updatedResult(taskId, `The pull request's title was updated from \`${param.pullRequestTitle}\` to \`${title}\`.`)]
70299
+ ? [updatedResult(taskId, `The pull request's title was updated from \`${currentTitle}\` to \`${title}\`.`)]
70142
70300
  : [skippedResult(taskId)];
70143
70301
  }
70144
70302
  function titleUpdateFailure(taskId, error) {
@@ -71916,13 +72074,13 @@ async function runLinkPullRequestIssue(param, taskId, port, delay) {
71916
72074
  let retainedIssueReference = false;
71917
72075
  let alreadyLinked = false;
71918
72076
  if (!hasOwnedPendingOperation) {
71919
- alreadyLinked = await port.isLinked(param.pullRequestNumber);
72077
+ alreadyLinked = await port.isLinked(param.pullRequestNumber, param.issueNumber);
71920
72078
  if (alreadyLinked)
71921
72079
  return [];
71922
72080
  }
71923
72081
  else {
71924
72082
  try {
71925
- alreadyLinked = await port.isLinked(param.pullRequestNumber);
72083
+ alreadyLinked = await port.isLinked(param.pullRequestNumber, param.issueNumber);
71926
72084
  }
71927
72085
  catch (error) {
71928
72086
  primaryError = error;
@@ -73489,6 +73647,7 @@ exports.registerSetupCommand = registerSetupCommand;
73489
73647
  const product_identity_1 = __nccwpck_require__(18739);
73490
73648
  const setup_command_options_1 = __nccwpck_require__(99254);
73491
73649
  const setup_execution_1 = __nccwpck_require__(51293);
73650
+ const setup_documentation_1 = __nccwpck_require__(2396);
73492
73651
  function registerSetupCommand(program) {
73493
73652
  program
73494
73653
  .command('setup')
@@ -73522,6 +73681,7 @@ function registerSetupCommand(program) {
73522
73681
  .option('--update-workflows', 'Allow setup-managed workflows already in the repository to be updated', false)
73523
73682
  .option('--workflow-pat <token>', 'Workflow PAT for the bot account (prefer the hidden interactive prompt)')
73524
73683
  .option('--secret <name=value>', 'Secret value for non-interactive setup; repeat for each API key', setup_command_options_1.collectSecret, {})
73684
+ .addHelpText('after', `\nGuides (open only when you choose):\n Web setup tutorial: ${setup_documentation_1.SETUP_DOCUMENTATION.tutorial}\n First issue-to-PR workflow: ${setup_documentation_1.SETUP_DOCUMENTATION.firstWorkflow}\n Troubleshooting: ${setup_documentation_1.SETUP_DOCUMENTATION.recovery}\n\nDuring interactive setup, type ? for question help and :back to revisit an answer.\n`)
73525
73685
  .action(setup_execution_1.executeSetupCommand);
73526
73686
  }
73527
73687
 
@@ -75435,9 +75595,19 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
75435
75595
  exports.ConsoleSetupJourneyPresenter = void 0;
75436
75596
  exports.renderSetupJourney = renderSetupJourney;
75437
75597
  const setup_prompt_rendering_1 = __nccwpck_require__(76673);
75598
+ const setup_documentation_1 = __nccwpck_require__(2396);
75438
75599
  class ConsoleSetupJourneyPresenter {
75439
75600
  present(view) {
75440
75601
  console.log(renderSetupJourney(view));
75602
+ if (view.outcome === 'complete') {
75603
+ console.log(`Next: install the reviewed files, then verify your first workflow: ${setup_documentation_1.SETUP_DOCUMENTATION.firstWorkflow}`);
75604
+ }
75605
+ else if (view.outcome === 'blocked' || view.outcome === 'partial') {
75606
+ console.log(`Inspect the result before retrying. Troubleshooting: ${setup_documentation_1.SETUP_DOCUMENTATION.recovery}`);
75607
+ }
75608
+ else if (view.current === 'Repository' || view.outcome === 'dry-run') {
75609
+ console.log(`Setup tutorial (opens only when you choose): ${setup_documentation_1.SETUP_DOCUMENTATION.tutorial}`);
75610
+ }
75441
75611
  }
75442
75612
  }
75443
75613
  exports.ConsoleSetupJourneyPresenter = ConsoleSetupJourneyPresenter;
@@ -78106,6 +78276,12 @@ exports.APPLICATION_ERROR_METADATA = {
78106
78276
  action: 'Correct the input and retry.',
78107
78277
  retainedState: UNCHANGED_STATE,
78108
78278
  },
78279
+ 'validation.evidence-unavailable': {
78280
+ kind: 'validation', retryable: false,
78281
+ impact: 'Progress was not assessed because GitHub omitted a required file patch.',
78282
+ action: 'Inspect the exact base/head comparison manually or split the work into smaller reviewed changes with complete patches before a new assessment. Retrying the same commits cannot restore omitted evidence.',
78283
+ retainedState: 'Existing progress labels and published assessments were preserved; no model assessment was made.',
78284
+ },
78109
78285
  'validation.evidence-too-large': {
78110
78286
  kind: 'validation', retryable: false,
78111
78287
  impact: 'Progress could not be assessed within the fixed evidence limits.',
@@ -84725,6 +84901,7 @@ exports.IssueProgressTrackingRepository = IssueProgressTrackingRepository;
84725
84901
  Object.defineProperty(exports, "__esModule", ({ value: true }));
84726
84902
  exports.IssueTitleRepository = void 0;
84727
84903
  const issue_emoji_policy_1 = __nccwpck_require__(81201);
84904
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
84728
84905
  const issue_title_policy_1 = __nccwpck_require__(83179);
84729
84906
  const issue_title_update_1 = __nccwpck_require__(9229);
84730
84907
  class IssueTitleRepository {
@@ -84742,10 +84919,12 @@ class IssueTitleRepository {
84742
84919
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, issueTitle, formattedTitle, issueNumber, token);
84743
84920
  });
84744
84921
  };
84745
- this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, branchManagementEmoji, labels, token) => {
84922
+ this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, _branchManagementEmoji, labels, token) => {
84746
84923
  return (0, issue_title_update_1.withTitleUpdateLogging)(() => {
84747
- const emoji = (0, issue_emoji_policy_1.resolvePullRequestTitleEmoji)(labels, branchManagementEmoji);
84748
- const formattedTitle = `[#${issueNumber}] ${emoji} - ${(0, issue_title_policy_1.sanitizePullRequestTitle)((0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber))}`;
84924
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(pullRequestTitle))
84925
+ return Promise.resolve(undefined);
84926
+ const sourceTitle = (0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber);
84927
+ const formattedTitle = (0, pull_request_title_policy_1.generatedPullRequestTitle)(sourceTitle, (0, issue_title_policy_1.sanitizePullRequestTitle)(sourceTitle), issueNumber, labels);
84749
84928
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, pullRequestTitle, formattedTitle, pullRequestNumber, token);
84750
84929
  });
84751
84930
  };
@@ -85414,8 +85593,10 @@ class ProgressDiffRepository {
85414
85593
  throw unavailable();
85415
85594
  paths.add(path);
85416
85595
  const generated = path.startsWith('build/') || path === 'specs/CATALOG.md';
85417
- if (!generated && (file.additions > 0 || file.deletions > 0) && (typeof file.patch !== 'string' || !file.patch))
85418
- throw unavailable();
85596
+ const unchanged = file.status === 'unchanged' && file.additions === 0 && file.deletions === 0;
85597
+ if (!generated && !unchanged && (typeof file.patch !== 'string' || !file.patch)) {
85598
+ throw new application_error_1.ApplicationError('validation.evidence-unavailable', 'GitHub omitted a required file patch from the pinned comparison. Progress was not assessed and existing state was retained.');
85599
+ }
85419
85600
  return { path, status: file.status, additions: file.additions, deletions: file.deletions,
85420
85601
  ...(generated ? { evidence: 'generated-metadata-only' } : { patch: file.patch ?? '' }) };
85421
85602
  });
@@ -86701,6 +86882,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
86701
86882
  exports.PullRequestLifecycleRepository = void 0;
86702
86883
  const logger_1 = __nccwpck_require__(91151);
86703
86884
  const application_error_1 = __nccwpck_require__(75999);
86885
+ const github_error_policy_1 = __nccwpck_require__(58791);
86704
86886
  class PullRequestLifecycleRepository {
86705
86887
  constructor(githubClient) {
86706
86888
  this.githubClient = githubClient;
@@ -86762,26 +86944,69 @@ class PullRequestLifecycleRepository {
86762
86944
  throw semanticError;
86763
86945
  }
86764
86946
  };
86765
- this.isLinked = async (owner, repository, pullRequestNumber, _token) => {
86766
- const pullRequestUrl = `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/pull/${pullRequestNumber}`;
86767
- const controller = new AbortController();
86768
- const timeoutId = setTimeout(() => controller.abort(), PullRequestLifecycleRepository.IS_LINKED_FETCH_TIMEOUT_MS);
86947
+ /** Reads at most 200 closing references through the credential-bound API. */
86948
+ this.isLinked = async (owner, repository, pullRequestNumber, issueNumber, token) => {
86769
86949
  try {
86770
- const res = await fetch(pullRequestUrl, { signal: controller.signal });
86771
- if (!res.ok) {
86772
- throw new Error(`Pull-request linkage query returned HTTP ${res.status}.`);
86950
+ if (![pullRequestNumber, issueNumber].every(number => Number.isSafeInteger(number) && number > 0)) {
86951
+ throw new application_error_1.ApplicationError('validation.invalid-input', 'Linkage requires positive PR and issue numbers.');
86952
+ }
86953
+ const client = this.githubClient.getClient(token);
86954
+ if (!client.graphql)
86955
+ throw new application_error_1.ApplicationError('configuration.unsupported', 'Authenticated PR linkage queries are not supported by this installation.');
86956
+ const expectedRepository = `${owner}/${repository}`.toLowerCase();
86957
+ let cursor = null;
86958
+ for (let page = 0; page < 2; page += 1) {
86959
+ const result = await client.graphql(`
86960
+ query PullRequestIssueLinkage($owner: String!, $repo: String!, $number: Int!, $cursor: String) {
86961
+ repository(owner: $owner, name: $repo) {
86962
+ nameWithOwner
86963
+ pullRequest(number: $number) {
86964
+ number
86965
+ closingIssuesReferences(first: 100, after: $cursor) {
86966
+ nodes { number repository { nameWithOwner } }
86967
+ pageInfo { hasNextPage endCursor }
86968
+ }
86969
+ }
86970
+ }
86971
+ }`, { owner, repo: repository, number: pullRequestNumber, cursor });
86972
+ const resource = result?.repository;
86973
+ if (resource === null || resource?.pullRequest === null) {
86974
+ throw new application_error_1.ApplicationError('provider.not-found', 'The requested pull request is unavailable to the configured credential.');
86975
+ }
86976
+ const pr = resource?.pullRequest;
86977
+ const references = pr?.closingIssuesReferences;
86978
+ if (typeof resource?.nameWithOwner !== 'string' || resource.nameWithOwner.toLowerCase() !== expectedRepository || pr?.number !== pullRequestNumber
86979
+ || !Array.isArray(references?.nodes) || references.nodes.length > 100
86980
+ || typeof references.pageInfo?.hasNextPage !== 'boolean'
86981
+ || references.nodes.some(node => !node || !Number.isSafeInteger(node.number) || node.number <= 0
86982
+ || typeof node.repository?.nameWithOwner !== 'string' || !node.repository.nameWithOwner)) {
86983
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'GitHub did not return verifiable PR linkage evidence.');
86984
+ }
86985
+ if (references.nodes.some(node => node.number === issueNumber
86986
+ && node.repository.nameWithOwner.toLowerCase() === expectedRepository))
86987
+ return true;
86988
+ if (!references.pageInfo.hasNextPage)
86989
+ return false;
86990
+ const nextCursor = references.pageInfo.endCursor;
86991
+ if (typeof nextCursor !== 'string' || !nextCursor || nextCursor === cursor) {
86992
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'GitHub returned incomplete linkage pagination.');
86993
+ }
86994
+ cursor = nextCursor;
86773
86995
  }
86774
- const htmlContent = await res.text();
86775
- return !htmlContent.includes('has_github_issues=false');
86996
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'PR linkage exceeds the fixed 200-reference inspection bound.');
86776
86997
  }
86777
86998
  catch (error) {
86778
- const semanticError = (0, application_error_1.toApplicationError)(error, 'provider.unavailable', `Unable to inspect issue linkage for pull request #${pullRequestNumber}.`);
86999
+ const status = (0, github_error_policy_1.getGithubErrorStatus)(error);
87000
+ const types = typeof error === 'object' && error !== null && 'errors' in error && Array.isArray(error.errors)
87001
+ ? error.errors.map((entry) => entry?.type) : [];
87002
+ const code = (0, github_error_policy_1.isGithubRateLimited)(error) || types.includes('RATE_LIMITED') ? 'provider.rate-limited'
87003
+ : status === 401 ? 'authorization.credential-invalid'
87004
+ : status === 403 || types.includes('FORBIDDEN') || types.includes('UNAUTHORIZED') ? 'authorization.denied'
87005
+ : status === 404 || types.includes('NOT_FOUND') ? 'provider.not-found' : 'provider.unavailable';
87006
+ const semanticError = (0, application_error_1.toApplicationError)(error, code, `Unable to inspect issue linkage for pull request #${pullRequestNumber}.`);
86779
87007
  (0, logger_1.logError)(semanticError);
86780
87008
  throw semanticError;
86781
87009
  }
86782
- finally {
86783
- clearTimeout(timeoutId);
86784
- }
86785
87010
  };
86786
87011
  this.updateBaseBranch = async (owner, repository, pullRequestNumber, branch, token) => {
86787
87012
  const octokit = this.githubClient.getClient(token);
@@ -86850,8 +87075,6 @@ class PullRequestLifecycleRepository {
86850
87075
  }
86851
87076
  }
86852
87077
  exports.PullRequestLifecycleRepository = PullRequestLifecycleRepository;
86853
- /** Default timeout (ms) for isLinked fetch. */
86854
- PullRequestLifecycleRepository.IS_LINKED_FETCH_TIMEOUT_MS = 10000;
86855
87078
  function toBugbotPullRequestIdentity(value) {
86856
87079
  const number = value.number;
86857
87080
  const state = value.state;
@@ -94970,7 +95193,7 @@ function bindBranchWorkflow(port, binding) {
94970
95193
  }
94971
95194
  function bindPullRequestIssueLink(port, binding) {
94972
95195
  return Object.freeze({
94973
- isLinked: (pullRequestNumber) => port.isLinked(binding.owner, binding.repository, pullRequestNumber, binding.token),
95196
+ isLinked: (pullRequestNumber, issueNumber) => port.isLinked(binding.owner, binding.repository, pullRequestNumber, issueNumber, binding.token),
94974
95197
  getDetails: (pullRequestNumber) => port.getDetails(binding.owner, binding.repository, pullRequestNumber, binding.token),
94975
95198
  updateBaseBranch: (pullRequestNumber, baseBranch) => port.updateBaseBranch(binding.owner, binding.repository, pullRequestNumber, baseBranch, binding.token),
94976
95199
  updateDescription: (pullRequestNumber, description) => port.updateDescription(binding.owner, binding.repository, pullRequestNumber, description, binding.token),
@@ -96336,6 +96559,7 @@ const exec = __importStar(__nccwpck_require__(18538));
96336
96559
  const git_authentication_environment_1 = __nccwpck_require__(16535);
96337
96560
  const untrusted_command_environment_1 = __nccwpck_require__(2304);
96338
96561
  const git_hook_isolation_1 = __nccwpck_require__(39764);
96562
+ const verification_runtime_preflight_1 = __nccwpck_require__(23100);
96339
96563
  class GitCommitAdapter {
96340
96564
  constructor(executeCommand = (program, args, options) => options
96341
96565
  ? exec.exec(program, args, {
@@ -96345,16 +96569,21 @@ class GitCommitAdapter {
96345
96569
  ...(options.stdout ? { listeners: { stdout: options.stdout } } : {}),
96346
96570
  ...(options.env ? { env: options.env } : {}),
96347
96571
  })
96348
- : exec.exec(program, args)) {
96572
+ : exec.exec(program, args), checkPrerequisites = verification_runtime_preflight_1.assertVerificationRuntimePrerequisites) {
96349
96573
  this.executeCommand = executeCommand;
96574
+ this.checkPrerequisites = checkPrerequisites;
96350
96575
  }
96351
96576
  async execute(program, args, options) {
96577
+ if (options?.verifyRuntimePrerequisites && !options.untrusted)
96578
+ throw new Error('Runtime preflight requires credential-free verification.');
96352
96579
  if (!options?.untrusted)
96353
96580
  return options ? this.executeCommand(program, args, options) : this.executeCommand(program, args);
96354
96581
  if (options.env)
96355
96582
  throw new Error('Untrusted command execution does not accept a caller-supplied environment.');
96356
96583
  const runtime = (0, untrusted_command_environment_1.prepareUntrustedCommandEnvironment)();
96357
96584
  try {
96585
+ if (options.verifyRuntimePrerequisites)
96586
+ this.checkPrerequisites(runtime.environment);
96358
96587
  return await this.executeCommand(program, args, {
96359
96588
  ...(options.stdout ? { stdout: options.stdout } : {}),
96360
96589
  env: runtime.environment,
@@ -101835,6 +102064,7 @@ const node_path_1 = __nccwpck_require__(49411);
101835
102064
  const agent_private_install_root_1 = __nccwpck_require__(44640);
101836
102065
  const ALLOWED_VARIABLES = [
101837
102066
  'PATH',
102067
+ 'JAVA_HOME',
101838
102068
  'LANG',
101839
102069
  'LANGUAGE',
101840
102070
  'LC_ALL',
@@ -101894,6 +102124,132 @@ function prepareUntrustedCommandEnvironment(source = process.env, platform = pro
101894
102124
  }
101895
102125
 
101896
102126
 
102127
+ /***/ }),
102128
+
102129
+ /***/ 91053:
102130
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
102131
+
102132
+ "use strict";
102133
+
102134
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
102135
+ exports.readVerificationRuntimeManifest = readVerificationRuntimeManifest;
102136
+ const node_fs_1 = __nccwpck_require__(87561);
102137
+ const node_path_1 = __nccwpck_require__(49411);
102138
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
102139
+ const MAX_MANIFEST_BYTES = 16 * 1024;
102140
+ function readVerificationRuntimeManifest(root) {
102141
+ const path = (0, node_path_1.resolve)(root, verification_runtime_policy_1.VERIFICATION_RUNTIME_MANIFEST);
102142
+ let descriptor;
102143
+ try {
102144
+ let directory;
102145
+ try {
102146
+ directory = (0, node_fs_1.lstatSync)((0, node_path_1.join)(root, '.copilot'));
102147
+ }
102148
+ catch (error) {
102149
+ if (error.code === 'ENOENT')
102150
+ return [];
102151
+ throw error;
102152
+ }
102153
+ if (!directory.isDirectory() || directory.isSymbolicLink()
102154
+ || (0, node_fs_1.realpathSync)((0, node_path_1.join)(root, '.copilot')) !== (0, node_path_1.join)((0, node_fs_1.realpathSync)(root), '.copilot'))
102155
+ throw new Error('Unsafe manifest parent');
102156
+ let entry;
102157
+ try {
102158
+ entry = (0, node_fs_1.lstatSync)(path, { bigint: true });
102159
+ }
102160
+ catch (error) {
102161
+ if (error.code === 'ENOENT')
102162
+ return [];
102163
+ throw error;
102164
+ }
102165
+ if (!entry.isFile() || entry.isSymbolicLink() || entry.nlink !== 1n || entry.size > BigInt(MAX_MANIFEST_BYTES))
102166
+ throw new Error('Unsafe manifest');
102167
+ descriptor = (0, node_fs_1.openSync)(path, node_fs_1.constants.O_RDONLY | (node_fs_1.constants.O_NOFOLLOW ?? 0));
102168
+ const opened = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
102169
+ if (!opened.isFile() || opened.nlink !== 1n || opened.dev !== entry.dev || opened.ino !== entry.ino
102170
+ || opened.size > BigInt(MAX_MANIFEST_BYTES))
102171
+ throw new Error('Manifest changed');
102172
+ const bytes = Buffer.alloc(MAX_MANIFEST_BYTES + 1);
102173
+ const size = (0, node_fs_1.readSync)(descriptor, bytes, 0, bytes.length, 0);
102174
+ if (size > MAX_MANIFEST_BYTES)
102175
+ throw new Error('Oversized manifest');
102176
+ return (0, verification_runtime_policy_1.parseVerificationRuntimeManifest)(JSON.parse(bytes.subarray(0, size).toString('utf8')));
102177
+ }
102178
+ catch {
102179
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('manifest-invalid');
102180
+ }
102181
+ finally {
102182
+ if (descriptor !== undefined)
102183
+ (0, node_fs_1.closeSync)(descriptor);
102184
+ }
102185
+ }
102186
+
102187
+
102188
+ /***/ }),
102189
+
102190
+ /***/ 23100:
102191
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
102192
+
102193
+ "use strict";
102194
+
102195
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
102196
+ exports.assertVerificationRuntimePrerequisites = assertVerificationRuntimePrerequisites;
102197
+ const node_child_process_1 = __nccwpck_require__(17718);
102198
+ const node_path_1 = __nccwpck_require__(49411);
102199
+ const verification_runtime_manifest_1 = __nccwpck_require__(91053);
102200
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
102201
+ const probe = (program, args, environment) => {
102202
+ const result = (0, node_child_process_1.spawnSync)(program, [...args], { env: environment, encoding: 'utf8', shell: false,
102203
+ windowsHide: true, timeout: 5000, maxBuffer: 8192, stdio: ['ignore', 'pipe', 'pipe'] });
102204
+ return { status: result.status, output: `${result.stdout ?? ''}\n${result.stderr ?? ''}`, failed: !!result.error };
102205
+ };
102206
+ const hasControlCharacter = (value) => [...value].some(character => character.charCodeAt(0) < 32);
102207
+ /** Fixed version probes only; never installs a runtime or executes a repository-provided bootstrap. */
102208
+ function assertVerificationRuntimePrerequisites(environment, root = process.cwd(), run = probe, platform = process.platform, job = process.env.GITHUB_JOB) {
102209
+ for (const requirement of (0, verification_runtime_manifest_1.readVerificationRuntimeManifest)(root)) {
102210
+ checkRuntime(requirement, environment, run, platform, job);
102211
+ }
102212
+ }
102213
+ function checkRuntime(requirement, environment, run, platform, job) {
102214
+ const spec = verification_runtime_policy_1.VERIFICATION_RUNTIME_SPECS[requirement.runtime];
102215
+ let program = spec.program;
102216
+ let args = spec.args;
102217
+ if (requirement.runtime === 'java' && environment.JAVA_HOME) {
102218
+ const paths = platform === 'win32' ? node_path_1.win32 : node_path_1.posix;
102219
+ if (!paths.isAbsolute(environment.JAVA_HOME) || hasControlCharacter(environment.JAVA_HOME)) {
102220
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
102221
+ }
102222
+ program = paths.join(environment.JAVA_HOME, 'bin', platform === 'win32' ? 'java.exe' : 'java');
102223
+ }
102224
+ else if (requirement.runtime === 'python' && platform === 'win32')
102225
+ program = 'python';
102226
+ else if (requirement.runtime === 'pnpm' && platform === 'win32') {
102227
+ const systemRoot = environment.SystemRoot;
102228
+ if (!systemRoot || !node_path_1.win32.isAbsolute(systemRoot) || hasControlCharacter(systemRoot)) {
102229
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
102230
+ }
102231
+ program = node_path_1.win32.join(systemRoot, 'System32', 'cmd.exe');
102232
+ args = ['/d', '/s', '/c', 'pnpm --version'];
102233
+ }
102234
+ let result;
102235
+ try {
102236
+ result = run(program, args, environment);
102237
+ }
102238
+ catch {
102239
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
102240
+ }
102241
+ if (result.failed || result.status !== 0 || result.output.length > 8192) {
102242
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
102243
+ }
102244
+ const observed = (0, verification_runtime_policy_1.verificationRuntimeVersion)(requirement.runtime, result.output);
102245
+ if (!observed)
102246
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unreadable-version', requirement, undefined, job);
102247
+ if (!(0, verification_runtime_policy_1.verificationRuntimeMatches)(requirement.version, observed)) {
102248
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('version-mismatch', requirement, observed, job);
102249
+ }
102250
+ }
102251
+
102252
+
101897
102253
  /***/ }),
101898
102254
 
101899
102255
  /***/ 92540: