@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.
@@ -40545,6 +40545,11 @@ const SPANISH_CONTENT = Object.freeze({
40545
40545
  action: 'Corrige la entrada y reinténtalo.',
40546
40546
  retainedState: UNCHANGED_STATE_ES,
40547
40547
  }),
40548
+ 'validation.evidence-unavailable': Object.freeze({
40549
+ impact: 'No se evaluó el progreso porque GitHub omitió un patch necesario.',
40550
+ 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.',
40551
+ retainedState: 'Se conservaron las etiquetas de progreso y las evaluaciones publicadas; no se realizó ninguna evaluación del modelo.',
40552
+ }),
40548
40553
  'validation.evidence-too-large': Object.freeze({
40549
40554
  impact: 'No se pudo evaluar el progreso dentro de los límites fijos de evidencia.',
40550
40555
  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.',
@@ -47336,6 +47341,34 @@ function verifiedReadinessLink(snapshot, number) {
47336
47341
  }
47337
47342
 
47338
47343
 
47344
+ /***/ }),
47345
+
47346
+ /***/ 59756:
47347
+ /***/ ((__unused_webpack_module, exports) => {
47348
+
47349
+ "use strict";
47350
+
47351
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
47352
+ exports.hasConventionalPullRequestTitle = hasConventionalPullRequestTitle;
47353
+ exports.generatedPullRequestTitle = generatedPullRequestTitle;
47354
+ /** Recognizes the conventional header shape; the consumer's CI owns its allowed types and subject rules. */
47355
+ function hasConventionalPullRequestTitle(title) {
47356
+ return !title.includes('\n') && !title.includes('\r')
47357
+ && /^\p{L}[\p{L}\p{N}_-]*(?:\([^()\r\n]+\))?!?: +\S[^\r\n]*$/u.test(title);
47358
+ }
47359
+ function generatedPullRequestTitle(sourceTitle, sanitizedSubject, issueNumber, labels) {
47360
+ if (hasConventionalPullRequestTitle(sourceTitle))
47361
+ return sourceTitle;
47362
+ const type = labels.isHotfix || labels.isBugfix || labels.isBug ? 'fix'
47363
+ : labels.isFeature || labels.isEnhancement ? 'feat'
47364
+ : labels.isDocs || labels.isDocumentation ? 'docs' : 'chore';
47365
+ const prefix = `${type}: `;
47366
+ const suffix = ` (#${issueNumber})`;
47367
+ const subject = (sanitizedSubject || 'Update linked issue').slice(0, 256 - prefix.length - suffix.length).trimEnd();
47368
+ return `${prefix}${subject}${suffix}`;
47369
+ }
47370
+
47371
+
47339
47372
  /***/ }),
47340
47373
 
47341
47374
  /***/ 39410:
@@ -47527,6 +47560,12 @@ Do not add the \`${profile.deployment.launcherLabel}\` label, dispatch a deploym
47527
47560
 
47528
47561
  Never expose credentials, tokens, private keys, or other secrets in issues, commits, pull requests, logs, or diagnostic comments.
47529
47562
 
47563
+ ## Repository verification prerequisites
47564
+
47565
+ 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.
47566
+
47567
+ 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).
47568
+
47530
47569
  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).
47531
47570
  `;
47532
47571
  }
@@ -50733,6 +50772,87 @@ function projectCurrentNativeStatus(status, facts) {
50733
50772
  }
50734
50773
 
50735
50774
 
50775
+ /***/ }),
50776
+
50777
+ /***/ 89347:
50778
+ /***/ ((__unused_webpack_module, exports) => {
50779
+
50780
+ "use strict";
50781
+
50782
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
50783
+ exports.VerificationPrerequisiteError = exports.VERIFICATION_RUNTIME_SPECS = exports.VERIFICATION_RUNTIME_HELP = exports.VERIFICATION_RUNTIME_MANIFEST = void 0;
50784
+ exports.parseVerificationRuntimeManifest = parseVerificationRuntimeManifest;
50785
+ exports.verificationRuntimeVersion = verificationRuntimeVersion;
50786
+ exports.verificationRuntimeMatches = verificationRuntimeMatches;
50787
+ exports.VERIFICATION_RUNTIME_MANIFEST = '.copilot/verification-prerequisites.json';
50788
+ exports.VERIFICATION_RUNTIME_HELP = 'https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites';
50789
+ exports.VERIFICATION_RUNTIME_SPECS = {
50790
+ java: { label: 'Java', program: 'java', args: ['-version'] },
50791
+ node: { label: 'Node.js', program: 'node', args: ['--version'] },
50792
+ pnpm: { label: 'pnpm', program: 'pnpm', args: ['--version'] },
50793
+ python: { label: 'Python', program: 'python3', args: ['--version'] },
50794
+ go: { label: 'Go', program: 'go', args: ['version'] },
50795
+ dotnet: { label: '.NET SDK', program: 'dotnet', args: ['--version'] },
50796
+ ruby: { label: 'Ruby', program: 'ruby', args: ['--version'] },
50797
+ rust: { label: 'Rust', program: 'rustc', args: ['--version'] },
50798
+ };
50799
+ const VERSION_PREFIX = /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,2}$/u;
50800
+ /** Only reviewed, closed runtime/version facts enter user-visible diagnostics. Raw tool output never does. */
50801
+ class VerificationPrerequisiteError extends Error {
50802
+ constructor(reason, requirement, observed, job) {
50803
+ const jobLabel = job && /^[A-Za-z_][A-Za-z0-9_-]{0,99}$/u.test(job) ? ` in job ${job}` : ' in this job';
50804
+ const runtime = requirement && Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, requirement.runtime)
50805
+ ? exports.VERIFICATION_RUNTIME_SPECS[requirement.runtime].label : 'Required runtime';
50806
+ const version = requirement && VERSION_PREFIX.test(requirement.version) ? requirement.version : 'declared version';
50807
+ const actual = observed && /^[1-9]\d{0,2}(?:\.(?:0|[1-9]\d{0,2})){0,3}$/u.test(observed) ? observed : 'unavailable';
50808
+ const cause = reason === 'manifest-invalid' ? `${exports.VERIFICATION_RUNTIME_MANIFEST} is invalid or unsafe`
50809
+ : reason === 'version-mismatch' ? `${runtime} ${version} is required; observed ${actual}`
50810
+ : reason === 'unreadable-version' ? `${runtime} ${version} could not be verified`
50811
+ : `${runtime} ${version} is unavailable`;
50812
+ const action = reason === 'manifest-invalid' ? 'Correct the reviewed runtime declaration.'
50813
+ : `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.' : ''}`;
50814
+ super(`Repository verification is blocked${jobLabel}: ${cause}. ${action} The repository verification command was not run. Help: ${exports.VERIFICATION_RUNTIME_HELP}`);
50815
+ this.name = 'VerificationPrerequisiteError';
50816
+ }
50817
+ }
50818
+ exports.VerificationPrerequisiteError = VerificationPrerequisiteError;
50819
+ function parseVerificationRuntimeManifest(value) {
50820
+ if (!value || typeof value !== 'object' || Array.isArray(value))
50821
+ throw new VerificationPrerequisiteError('manifest-invalid');
50822
+ const object = value;
50823
+ if (object.schemaVersion !== 1 || Object.keys(object).some(key => !['schemaVersion', 'runtimes'].includes(key))
50824
+ || !object.runtimes || typeof object.runtimes !== 'object' || Array.isArray(object.runtimes)) {
50825
+ throw new VerificationPrerequisiteError('manifest-invalid');
50826
+ }
50827
+ const runtimes = object.runtimes;
50828
+ if (Object.keys(runtimes).length > 8)
50829
+ throw new VerificationPrerequisiteError('manifest-invalid');
50830
+ return Object.entries(runtimes).map(([runtime, version]) => {
50831
+ if (!Object.prototype.hasOwnProperty.call(exports.VERIFICATION_RUNTIME_SPECS, runtime) || typeof version !== 'string' || !VERSION_PREFIX.test(version)) {
50832
+ throw new VerificationPrerequisiteError('manifest-invalid');
50833
+ }
50834
+ return Object.freeze({ runtime: runtime, version });
50835
+ });
50836
+ }
50837
+ function verificationRuntimeVersion(runtime, output) {
50838
+ const patterns = {
50839
+ java: /^(?:openjdk|java) (?:version )?["']?(\d+(?:\.\d+){0,3})/imu,
50840
+ node: /^v(\d+\.\d+\.\d+)/mu,
50841
+ pnpm: /^(\d+\.\d+\.\d+)/mu,
50842
+ python: /^Python (\d+\.\d+\.\d+)/mu,
50843
+ go: /^go version go(\d+\.\d+(?:\.\d+)?)/mu,
50844
+ dotnet: /^(\d+\.\d+\.\d+)/mu,
50845
+ ruby: /^ruby (\d+\.\d+\.\d+)/mu,
50846
+ rust: /^rustc (\d+\.\d+\.\d+)/mu,
50847
+ };
50848
+ const version = patterns[runtime].exec(output)?.[1];
50849
+ return runtime === 'java' && version?.startsWith('1.') ? version.slice(2) : version;
50850
+ }
50851
+ function verificationRuntimeMatches(required, observed) {
50852
+ return observed === required || observed.startsWith(`${required}.`);
50853
+ }
50854
+
50855
+
50736
50856
  /***/ }),
50737
50857
 
50738
50858
  /***/ 43193:
@@ -54960,7 +55080,7 @@ class SyncBranchUseCase {
54960
55080
  const commands = (0, verify_command_policy_1.limitVerifyCommands)([...context.verifyCommands]);
54961
55081
  if (commands.length === verify_command_policy_1.MAX_VERIFY_COMMANDS)
54962
55082
  (0, logging_ports_1.logInfo)(`Branch sync verification is capped at ${verify_command_policy_1.MAX_VERIFY_COMMANDS} commands.`);
54963
- const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true }));
55083
+ const verification = await (0, verify_command_runner_1.runVerifyCommands)(commands, (program, args) => this.git.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
54964
55084
  if (!verification.success) {
54965
55085
  return {
54966
55086
  commandCount: commands.length,
@@ -60801,7 +60921,7 @@ async function runVerification(context, gitCommitPort) {
60801
60921
  if (verifyCommands.length === 0)
60802
60922
  return undefined;
60803
60923
  (0, logging_ports_1.logInfo)(`Running ${verifyCommands.length} verify ${verifyCommands.length === 1 ? 'command' : 'commands'}...`);
60804
- const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true }));
60924
+ const verify = await (0, verify_command_runner_1.runVerifyCommands)(verifyCommands, (program, args) => gitCommitPort.execute(program, args, { untrusted: true, verifyRuntimePrerequisites: true }));
60805
60925
  return verify.success
60806
60926
  ? undefined
60807
60927
  : verify.error ?? `Verify command failed: ${verify.failedCommand ?? "unknown"}.`;
@@ -63024,6 +63144,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
63024
63144
  exports.runVerifyCommands = runVerifyCommands;
63025
63145
  const logging_ports_1 = __nccwpck_require__(6152);
63026
63146
  const verify_command_policy_1 = __nccwpck_require__(96031);
63147
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
63027
63148
  async function runVerifyCommands(commands, execute) {
63028
63149
  for (const command of commands) {
63029
63150
  const result = await executeVerifyCommand(command, execute);
@@ -63042,7 +63163,11 @@ async function executeVerifyCommand(command, execute) {
63042
63163
  ? { success: true }
63043
63164
  : { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
63044
63165
  }
63045
- catch {
63166
+ catch (error) {
63167
+ if (error instanceof verification_runtime_policy_1.VerificationPrerequisiteError) {
63168
+ return { success: false, failedCommand: formatCommandForDiagnostics(parsed),
63169
+ error: `${error.message} Verification command: ${formatCommandForDiagnostics(parsed)}.` };
63170
+ }
63046
63171
  (0, logging_ports_1.logError)('Verify command failed.');
63047
63172
  return { success: false, failedCommand: formatCommandForDiagnostics(parsed) };
63048
63173
  }
@@ -65759,6 +65884,7 @@ exports.titleUpdateFailure = titleUpdateFailure;
65759
65884
  const result_1 = __nccwpck_require__(73817);
65760
65885
  const application_error_1 = __nccwpck_require__(75999);
65761
65886
  const positive_integer_policy_1 = __nccwpck_require__(19879);
65887
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
65762
65888
  function projectUpdateTitleContext(source) {
65763
65889
  if (source.isIssue) {
65764
65890
  return Object.freeze({
@@ -65809,19 +65935,27 @@ async function runPullRequestTitleUpdate(param, taskId, issueRepository) {
65809
65935
  if (!linkedIssueNumber || linkedIssueNumber === param.pullRequestNumber) {
65810
65936
  return [skippedResult(taskId)];
65811
65937
  }
65938
+ const currentTitle = await issueRepository.getTitle(param.pullRequestNumber);
65939
+ if (currentTitle === undefined) {
65940
+ return [new result_1.Result({ id: taskId, success: false, executed: true,
65941
+ steps: ['The current pull request title could not be read. No title change was attempted.'],
65942
+ errors: [new application_error_1.ApplicationError('provider.unavailable', 'Unable to read the current pull request title.')] })];
65943
+ }
65944
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(currentTitle))
65945
+ return [skippedResult(taskId)];
65812
65946
  const issueTitle = await issueRepository.getTitle(linkedIssueNumber);
65813
65947
  if (issueTitle === undefined) {
65814
65948
  return [new result_1.Result({ id: taskId, success: false, executed: true, steps: ['Tried to update title, but there was a problem.'] })];
65815
65949
  }
65816
65950
  const title = await issueRepository.updatePullRequestTitle({
65817
- pullRequestTitle: param.pullRequestTitle,
65951
+ pullRequestTitle: currentTitle,
65818
65952
  issueTitle,
65819
65953
  issueNumber: linkedIssueNumber,
65820
65954
  pullRequestNumber: param.pullRequestNumber,
65821
65955
  labelFacts: param.labelFacts,
65822
65956
  });
65823
65957
  return title
65824
- ? [updatedResult(taskId, `The pull request's title was updated from \`${param.pullRequestTitle}\` to \`${title}\`.`)]
65958
+ ? [updatedResult(taskId, `The pull request's title was updated from \`${currentTitle}\` to \`${title}\`.`)]
65825
65959
  : [skippedResult(taskId)];
65826
65960
  }
65827
65961
  function titleUpdateFailure(taskId, error) {
@@ -67599,13 +67733,13 @@ async function runLinkPullRequestIssue(param, taskId, port, delay) {
67599
67733
  let retainedIssueReference = false;
67600
67734
  let alreadyLinked = false;
67601
67735
  if (!hasOwnedPendingOperation) {
67602
- alreadyLinked = await port.isLinked(param.pullRequestNumber);
67736
+ alreadyLinked = await port.isLinked(param.pullRequestNumber, param.issueNumber);
67603
67737
  if (alreadyLinked)
67604
67738
  return [];
67605
67739
  }
67606
67740
  else {
67607
67741
  try {
67608
- alreadyLinked = await port.isLinked(param.pullRequestNumber);
67742
+ alreadyLinked = await port.isLinked(param.pullRequestNumber, param.issueNumber);
67609
67743
  }
67610
67744
  catch (error) {
67611
67745
  primaryError = error;
@@ -68461,6 +68595,12 @@ exports.APPLICATION_ERROR_METADATA = {
68461
68595
  action: 'Correct the input and retry.',
68462
68596
  retainedState: UNCHANGED_STATE,
68463
68597
  },
68598
+ 'validation.evidence-unavailable': {
68599
+ kind: 'validation', retryable: false,
68600
+ impact: 'Progress was not assessed because GitHub omitted a required file patch.',
68601
+ 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.',
68602
+ retainedState: 'Existing progress labels and published assessments were preserved; no model assessment was made.',
68603
+ },
68464
68604
  'validation.evidence-too-large': {
68465
68605
  kind: 'validation', retryable: false,
68466
68606
  impact: 'Progress could not be assessed within the fixed evidence limits.',
@@ -75217,6 +75357,7 @@ exports.IssueProgressTrackingRepository = IssueProgressTrackingRepository;
75217
75357
  Object.defineProperty(exports, "__esModule", ({ value: true }));
75218
75358
  exports.IssueTitleRepository = void 0;
75219
75359
  const issue_emoji_policy_1 = __nccwpck_require__(81201);
75360
+ const pull_request_title_policy_1 = __nccwpck_require__(59756);
75220
75361
  const issue_title_policy_1 = __nccwpck_require__(83179);
75221
75362
  const issue_title_update_1 = __nccwpck_require__(9229);
75222
75363
  class IssueTitleRepository {
@@ -75234,10 +75375,12 @@ class IssueTitleRepository {
75234
75375
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, issueTitle, formattedTitle, issueNumber, token);
75235
75376
  });
75236
75377
  };
75237
- this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, branchManagementEmoji, labels, token) => {
75378
+ this.updateTitlePullRequestFormat = async (owner, repository, pullRequestTitle, issueTitle, issueNumber, pullRequestNumber, _branchManagementEmoji, labels, token) => {
75238
75379
  return (0, issue_title_update_1.withTitleUpdateLogging)(() => {
75239
- const emoji = (0, issue_emoji_policy_1.resolvePullRequestTitleEmoji)(labels, branchManagementEmoji);
75240
- const formattedTitle = `[#${issueNumber}] ${emoji} - ${(0, issue_title_policy_1.sanitizePullRequestTitle)((0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber))}`;
75380
+ if ((0, pull_request_title_policy_1.hasConventionalPullRequestTitle)(pullRequestTitle))
75381
+ return Promise.resolve(undefined);
75382
+ const sourceTitle = (0, issue_title_policy_1.normalizePullRequestSourceTitle)(issueTitle, issueNumber);
75383
+ const formattedTitle = (0, pull_request_title_policy_1.generatedPullRequestTitle)(sourceTitle, (0, issue_title_policy_1.sanitizePullRequestTitle)(sourceTitle), issueNumber, labels);
75241
75384
  return (0, issue_title_update_1.updateIssueTitle)(this.issueTitleClient, owner, repository, pullRequestTitle, formattedTitle, pullRequestNumber, token);
75242
75385
  });
75243
75386
  };
@@ -75906,8 +76049,10 @@ class ProgressDiffRepository {
75906
76049
  throw unavailable();
75907
76050
  paths.add(path);
75908
76051
  const generated = path.startsWith('build/') || path === 'specs/CATALOG.md';
75909
- if (!generated && (file.additions > 0 || file.deletions > 0) && (typeof file.patch !== 'string' || !file.patch))
75910
- throw unavailable();
76052
+ const unchanged = file.status === 'unchanged' && file.additions === 0 && file.deletions === 0;
76053
+ if (!generated && !unchanged && (typeof file.patch !== 'string' || !file.patch)) {
76054
+ 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.');
76055
+ }
75911
76056
  return { path, status: file.status, additions: file.additions, deletions: file.deletions,
75912
76057
  ...(generated ? { evidence: 'generated-metadata-only' } : { patch: file.patch ?? '' }) };
75913
76058
  });
@@ -77193,6 +77338,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
77193
77338
  exports.PullRequestLifecycleRepository = void 0;
77194
77339
  const logger_1 = __nccwpck_require__(91151);
77195
77340
  const application_error_1 = __nccwpck_require__(75999);
77341
+ const github_error_policy_1 = __nccwpck_require__(58791);
77196
77342
  class PullRequestLifecycleRepository {
77197
77343
  constructor(githubClient) {
77198
77344
  this.githubClient = githubClient;
@@ -77254,26 +77400,69 @@ class PullRequestLifecycleRepository {
77254
77400
  throw semanticError;
77255
77401
  }
77256
77402
  };
77257
- this.isLinked = async (owner, repository, pullRequestNumber, _token) => {
77258
- const pullRequestUrl = `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/pull/${pullRequestNumber}`;
77259
- const controller = new AbortController();
77260
- const timeoutId = setTimeout(() => controller.abort(), PullRequestLifecycleRepository.IS_LINKED_FETCH_TIMEOUT_MS);
77403
+ /** Reads at most 200 closing references through the credential-bound API. */
77404
+ this.isLinked = async (owner, repository, pullRequestNumber, issueNumber, token) => {
77261
77405
  try {
77262
- const res = await fetch(pullRequestUrl, { signal: controller.signal });
77263
- if (!res.ok) {
77264
- throw new Error(`Pull-request linkage query returned HTTP ${res.status}.`);
77406
+ if (![pullRequestNumber, issueNumber].every(number => Number.isSafeInteger(number) && number > 0)) {
77407
+ throw new application_error_1.ApplicationError('validation.invalid-input', 'Linkage requires positive PR and issue numbers.');
77408
+ }
77409
+ const client = this.githubClient.getClient(token);
77410
+ if (!client.graphql)
77411
+ throw new application_error_1.ApplicationError('configuration.unsupported', 'Authenticated PR linkage queries are not supported by this installation.');
77412
+ const expectedRepository = `${owner}/${repository}`.toLowerCase();
77413
+ let cursor = null;
77414
+ for (let page = 0; page < 2; page += 1) {
77415
+ const result = await client.graphql(`
77416
+ query PullRequestIssueLinkage($owner: String!, $repo: String!, $number: Int!, $cursor: String) {
77417
+ repository(owner: $owner, name: $repo) {
77418
+ nameWithOwner
77419
+ pullRequest(number: $number) {
77420
+ number
77421
+ closingIssuesReferences(first: 100, after: $cursor) {
77422
+ nodes { number repository { nameWithOwner } }
77423
+ pageInfo { hasNextPage endCursor }
77424
+ }
77425
+ }
77426
+ }
77427
+ }`, { owner, repo: repository, number: pullRequestNumber, cursor });
77428
+ const resource = result?.repository;
77429
+ if (resource === null || resource?.pullRequest === null) {
77430
+ throw new application_error_1.ApplicationError('provider.not-found', 'The requested pull request is unavailable to the configured credential.');
77431
+ }
77432
+ const pr = resource?.pullRequest;
77433
+ const references = pr?.closingIssuesReferences;
77434
+ if (typeof resource?.nameWithOwner !== 'string' || resource.nameWithOwner.toLowerCase() !== expectedRepository || pr?.number !== pullRequestNumber
77435
+ || !Array.isArray(references?.nodes) || references.nodes.length > 100
77436
+ || typeof references.pageInfo?.hasNextPage !== 'boolean'
77437
+ || references.nodes.some(node => !node || !Number.isSafeInteger(node.number) || node.number <= 0
77438
+ || typeof node.repository?.nameWithOwner !== 'string' || !node.repository.nameWithOwner)) {
77439
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'GitHub did not return verifiable PR linkage evidence.');
77440
+ }
77441
+ if (references.nodes.some(node => node.number === issueNumber
77442
+ && node.repository.nameWithOwner.toLowerCase() === expectedRepository))
77443
+ return true;
77444
+ if (!references.pageInfo.hasNextPage)
77445
+ return false;
77446
+ const nextCursor = references.pageInfo.endCursor;
77447
+ if (typeof nextCursor !== 'string' || !nextCursor || nextCursor === cursor) {
77448
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'GitHub returned incomplete linkage pagination.');
77449
+ }
77450
+ cursor = nextCursor;
77265
77451
  }
77266
- const htmlContent = await res.text();
77267
- return !htmlContent.includes('has_github_issues=false');
77452
+ throw new application_error_1.ApplicationError('provider.contract-invalid', 'PR linkage exceeds the fixed 200-reference inspection bound.');
77268
77453
  }
77269
77454
  catch (error) {
77270
- const semanticError = (0, application_error_1.toApplicationError)(error, 'provider.unavailable', `Unable to inspect issue linkage for pull request #${pullRequestNumber}.`);
77455
+ const status = (0, github_error_policy_1.getGithubErrorStatus)(error);
77456
+ const types = typeof error === 'object' && error !== null && 'errors' in error && Array.isArray(error.errors)
77457
+ ? error.errors.map((entry) => entry?.type) : [];
77458
+ const code = (0, github_error_policy_1.isGithubRateLimited)(error) || types.includes('RATE_LIMITED') ? 'provider.rate-limited'
77459
+ : status === 401 ? 'authorization.credential-invalid'
77460
+ : status === 403 || types.includes('FORBIDDEN') || types.includes('UNAUTHORIZED') ? 'authorization.denied'
77461
+ : status === 404 || types.includes('NOT_FOUND') ? 'provider.not-found' : 'provider.unavailable';
77462
+ const semanticError = (0, application_error_1.toApplicationError)(error, code, `Unable to inspect issue linkage for pull request #${pullRequestNumber}.`);
77271
77463
  (0, logger_1.logError)(semanticError);
77272
77464
  throw semanticError;
77273
77465
  }
77274
- finally {
77275
- clearTimeout(timeoutId);
77276
- }
77277
77466
  };
77278
77467
  this.updateBaseBranch = async (owner, repository, pullRequestNumber, branch, token) => {
77279
77468
  const octokit = this.githubClient.getClient(token);
@@ -77342,8 +77531,6 @@ class PullRequestLifecycleRepository {
77342
77531
  }
77343
77532
  }
77344
77533
  exports.PullRequestLifecycleRepository = PullRequestLifecycleRepository;
77345
- /** Default timeout (ms) for isLinked fetch. */
77346
- PullRequestLifecycleRepository.IS_LINKED_FETCH_TIMEOUT_MS = 10000;
77347
77534
  function toBugbotPullRequestIdentity(value) {
77348
77535
  const number = value.number;
77349
77536
  const state = value.state;
@@ -85470,7 +85657,7 @@ function bindBranchWorkflow(port, binding) {
85470
85657
  }
85471
85658
  function bindPullRequestIssueLink(port, binding) {
85472
85659
  return Object.freeze({
85473
- isLinked: (pullRequestNumber) => port.isLinked(binding.owner, binding.repository, pullRequestNumber, binding.token),
85660
+ isLinked: (pullRequestNumber, issueNumber) => port.isLinked(binding.owner, binding.repository, pullRequestNumber, issueNumber, binding.token),
85474
85661
  getDetails: (pullRequestNumber) => port.getDetails(binding.owner, binding.repository, pullRequestNumber, binding.token),
85475
85662
  updateBaseBranch: (pullRequestNumber, baseBranch) => port.updateBaseBranch(binding.owner, binding.repository, pullRequestNumber, baseBranch, binding.token),
85476
85663
  updateDescription: (pullRequestNumber, description) => port.updateDescription(binding.owner, binding.repository, pullRequestNumber, description, binding.token),
@@ -86656,6 +86843,7 @@ const exec = __importStar(__nccwpck_require__(18538));
86656
86843
  const git_authentication_environment_1 = __nccwpck_require__(16535);
86657
86844
  const untrusted_command_environment_1 = __nccwpck_require__(2304);
86658
86845
  const git_hook_isolation_1 = __nccwpck_require__(39764);
86846
+ const verification_runtime_preflight_1 = __nccwpck_require__(23100);
86659
86847
  class GitCommitAdapter {
86660
86848
  constructor(executeCommand = (program, args, options) => options
86661
86849
  ? exec.exec(program, args, {
@@ -86665,16 +86853,21 @@ class GitCommitAdapter {
86665
86853
  ...(options.stdout ? { listeners: { stdout: options.stdout } } : {}),
86666
86854
  ...(options.env ? { env: options.env } : {}),
86667
86855
  })
86668
- : exec.exec(program, args)) {
86856
+ : exec.exec(program, args), checkPrerequisites = verification_runtime_preflight_1.assertVerificationRuntimePrerequisites) {
86669
86857
  this.executeCommand = executeCommand;
86858
+ this.checkPrerequisites = checkPrerequisites;
86670
86859
  }
86671
86860
  async execute(program, args, options) {
86861
+ if (options?.verifyRuntimePrerequisites && !options.untrusted)
86862
+ throw new Error('Runtime preflight requires credential-free verification.');
86672
86863
  if (!options?.untrusted)
86673
86864
  return options ? this.executeCommand(program, args, options) : this.executeCommand(program, args);
86674
86865
  if (options.env)
86675
86866
  throw new Error('Untrusted command execution does not accept a caller-supplied environment.');
86676
86867
  const runtime = (0, untrusted_command_environment_1.prepareUntrustedCommandEnvironment)();
86677
86868
  try {
86869
+ if (options.verifyRuntimePrerequisites)
86870
+ this.checkPrerequisites(runtime.environment);
86678
86871
  return await this.executeCommand(program, args, {
86679
86872
  ...(options.stdout ? { stdout: options.stdout } : {}),
86680
86873
  env: runtime.environment,
@@ -87989,6 +88182,7 @@ const node_path_1 = __nccwpck_require__(49411);
87989
88182
  const agent_private_install_root_1 = __nccwpck_require__(44640);
87990
88183
  const ALLOWED_VARIABLES = [
87991
88184
  'PATH',
88185
+ 'JAVA_HOME',
87992
88186
  'LANG',
87993
88187
  'LANGUAGE',
87994
88188
  'LC_ALL',
@@ -88048,6 +88242,132 @@ function prepareUntrustedCommandEnvironment(source = process.env, platform = pro
88048
88242
  }
88049
88243
 
88050
88244
 
88245
+ /***/ }),
88246
+
88247
+ /***/ 91053:
88248
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
88249
+
88250
+ "use strict";
88251
+
88252
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88253
+ exports.readVerificationRuntimeManifest = readVerificationRuntimeManifest;
88254
+ const node_fs_1 = __nccwpck_require__(87561);
88255
+ const node_path_1 = __nccwpck_require__(49411);
88256
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
88257
+ const MAX_MANIFEST_BYTES = 16 * 1024;
88258
+ function readVerificationRuntimeManifest(root) {
88259
+ const path = (0, node_path_1.resolve)(root, verification_runtime_policy_1.VERIFICATION_RUNTIME_MANIFEST);
88260
+ let descriptor;
88261
+ try {
88262
+ let directory;
88263
+ try {
88264
+ directory = (0, node_fs_1.lstatSync)((0, node_path_1.join)(root, '.copilot'));
88265
+ }
88266
+ catch (error) {
88267
+ if (error.code === 'ENOENT')
88268
+ return [];
88269
+ throw error;
88270
+ }
88271
+ if (!directory.isDirectory() || directory.isSymbolicLink()
88272
+ || (0, node_fs_1.realpathSync)((0, node_path_1.join)(root, '.copilot')) !== (0, node_path_1.join)((0, node_fs_1.realpathSync)(root), '.copilot'))
88273
+ throw new Error('Unsafe manifest parent');
88274
+ let entry;
88275
+ try {
88276
+ entry = (0, node_fs_1.lstatSync)(path, { bigint: true });
88277
+ }
88278
+ catch (error) {
88279
+ if (error.code === 'ENOENT')
88280
+ return [];
88281
+ throw error;
88282
+ }
88283
+ if (!entry.isFile() || entry.isSymbolicLink() || entry.nlink !== 1n || entry.size > BigInt(MAX_MANIFEST_BYTES))
88284
+ throw new Error('Unsafe manifest');
88285
+ descriptor = (0, node_fs_1.openSync)(path, node_fs_1.constants.O_RDONLY | (node_fs_1.constants.O_NOFOLLOW ?? 0));
88286
+ const opened = (0, node_fs_1.fstatSync)(descriptor, { bigint: true });
88287
+ if (!opened.isFile() || opened.nlink !== 1n || opened.dev !== entry.dev || opened.ino !== entry.ino
88288
+ || opened.size > BigInt(MAX_MANIFEST_BYTES))
88289
+ throw new Error('Manifest changed');
88290
+ const bytes = Buffer.alloc(MAX_MANIFEST_BYTES + 1);
88291
+ const size = (0, node_fs_1.readSync)(descriptor, bytes, 0, bytes.length, 0);
88292
+ if (size > MAX_MANIFEST_BYTES)
88293
+ throw new Error('Oversized manifest');
88294
+ return (0, verification_runtime_policy_1.parseVerificationRuntimeManifest)(JSON.parse(bytes.subarray(0, size).toString('utf8')));
88295
+ }
88296
+ catch {
88297
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('manifest-invalid');
88298
+ }
88299
+ finally {
88300
+ if (descriptor !== undefined)
88301
+ (0, node_fs_1.closeSync)(descriptor);
88302
+ }
88303
+ }
88304
+
88305
+
88306
+ /***/ }),
88307
+
88308
+ /***/ 23100:
88309
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
88310
+
88311
+ "use strict";
88312
+
88313
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
88314
+ exports.assertVerificationRuntimePrerequisites = assertVerificationRuntimePrerequisites;
88315
+ const node_child_process_1 = __nccwpck_require__(17718);
88316
+ const node_path_1 = __nccwpck_require__(49411);
88317
+ const verification_runtime_manifest_1 = __nccwpck_require__(91053);
88318
+ const verification_runtime_policy_1 = __nccwpck_require__(89347);
88319
+ const probe = (program, args, environment) => {
88320
+ const result = (0, node_child_process_1.spawnSync)(program, [...args], { env: environment, encoding: 'utf8', shell: false,
88321
+ windowsHide: true, timeout: 5000, maxBuffer: 8192, stdio: ['ignore', 'pipe', 'pipe'] });
88322
+ return { status: result.status, output: `${result.stdout ?? ''}\n${result.stderr ?? ''}`, failed: !!result.error };
88323
+ };
88324
+ const hasControlCharacter = (value) => [...value].some(character => character.charCodeAt(0) < 32);
88325
+ /** Fixed version probes only; never installs a runtime or executes a repository-provided bootstrap. */
88326
+ function assertVerificationRuntimePrerequisites(environment, root = process.cwd(), run = probe, platform = process.platform, job = process.env.GITHUB_JOB) {
88327
+ for (const requirement of (0, verification_runtime_manifest_1.readVerificationRuntimeManifest)(root)) {
88328
+ checkRuntime(requirement, environment, run, platform, job);
88329
+ }
88330
+ }
88331
+ function checkRuntime(requirement, environment, run, platform, job) {
88332
+ const spec = verification_runtime_policy_1.VERIFICATION_RUNTIME_SPECS[requirement.runtime];
88333
+ let program = spec.program;
88334
+ let args = spec.args;
88335
+ if (requirement.runtime === 'java' && environment.JAVA_HOME) {
88336
+ const paths = platform === 'win32' ? node_path_1.win32 : node_path_1.posix;
88337
+ if (!paths.isAbsolute(environment.JAVA_HOME) || hasControlCharacter(environment.JAVA_HOME)) {
88338
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88339
+ }
88340
+ program = paths.join(environment.JAVA_HOME, 'bin', platform === 'win32' ? 'java.exe' : 'java');
88341
+ }
88342
+ else if (requirement.runtime === 'python' && platform === 'win32')
88343
+ program = 'python';
88344
+ else if (requirement.runtime === 'pnpm' && platform === 'win32') {
88345
+ const systemRoot = environment.SystemRoot;
88346
+ if (!systemRoot || !node_path_1.win32.isAbsolute(systemRoot) || hasControlCharacter(systemRoot)) {
88347
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88348
+ }
88349
+ program = node_path_1.win32.join(systemRoot, 'System32', 'cmd.exe');
88350
+ args = ['/d', '/s', '/c', 'pnpm --version'];
88351
+ }
88352
+ let result;
88353
+ try {
88354
+ result = run(program, args, environment);
88355
+ }
88356
+ catch {
88357
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88358
+ }
88359
+ if (result.failed || result.status !== 0 || result.output.length > 8192) {
88360
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unavailable', requirement, undefined, job);
88361
+ }
88362
+ const observed = (0, verification_runtime_policy_1.verificationRuntimeVersion)(requirement.runtime, result.output);
88363
+ if (!observed)
88364
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('unreadable-version', requirement, undefined, job);
88365
+ if (!(0, verification_runtime_policy_1.verificationRuntimeMatches)(requirement.version, observed)) {
88366
+ throw new verification_runtime_policy_1.VerificationPrerequisiteError('version-mismatch', requirement, observed, job);
88367
+ }
88368
+ }
88369
+
88370
+
88051
88371
  /***/ }),
88052
88372
 
88053
88373
  /***/ 92540:
@@ -0,0 +1 @@
1
+ .setup-help.svelte-1fzpnf1{margin-bottom:1.5rem}.help-links.svelte-1fzpnf1{flex-wrap:wrap;gap:.5rem 1.25rem;display:flex}a.svelte-1fzpnf1{text-underline-offset:.2em;font-size:.875rem}p.svelte-1fzpnf1{margin:.4rem 0 0;font-size:.8rem}code.svelte-1spw6vv,bdi.svelte-1spw6vv{overflow-wrap:anywhere}.runner-details.svelte-1spw6vv{margin-block:1rem}.installation-review.svelte-44ckab{min-width:0;margin-block:1.25rem}.routes.svelte-44ckab{padding-inline-start:1.25rem}.routes.svelte-44ckab li:where(.svelte-44ckab){padding-block:.5rem}code.svelte-44ckab,pre.svelte-44ckab,bdi.svelte-44ckab{white-space:pre-wrap;overflow-wrap:anywhere}pre.svelte-44ckab{max-height:28rem;padding:.75rem;font-size:.8rem;overflow:auto}details.svelte-44ckab{margin-block:.75rem}.batch-targets.svelte-17t72gm{gap:1rem;margin-block:1rem;display:grid}.batch-target.svelte-17t72gm{border:1px solid var(--line);border-radius:.8rem;min-width:0;padding:1rem}h3.svelte-17t72gm{overflow-wrap:anywhere;margin-top:0}.target-status.svelte-17t72gm{font-weight:600}pre.svelte-17t72gm{max-height:24rem;padding:.75rem;font-size:.78rem;overflow:auto}code.svelte-17t72gm{overflow-wrap:anywhere}details.svelte-17t72gm{margin-block:.75rem}.batch-buttons.svelte-17t72gm{flex-wrap:wrap;gap:.75rem;display:flex}.batch-technical.svelte-17t72gm{margin-top:1.25rem}fieldset.svelte-1qngno{border:0;min-width:0;margin:1rem 0;padding:0}legend.svelte-1qngno{margin-bottom:.5rem;font-weight:600}.repository-list.svelte-1qngno{gap:.5rem;display:grid}.repository-row.svelte-1qngno{border:1px solid var(--line);border-radius:.75rem;align-items:start;gap:.75rem;padding:.75rem;display:flex}.repository-row.svelte-1qngno input:where(.svelte-1qngno){flex:none;width:auto;margin-top:.25rem}.repository-row.svelte-1qngno span:where(.svelte-1qngno){overflow-wrap:anywhere;min-width:0}.repository-row.svelte-1qngno small:where(.svelte-1qngno){margin-top:.25rem;display:block}.batch-actions.svelte-1qngno{flex-wrap:wrap;align-items:center;gap:.5rem;margin:.75rem 0;display:flex}details.svelte-1qngno{margin:1rem 0}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--page:#f6f8f7;--side:#102423;--side-line:#31504b;--side-text:#e8f5f0;--surface:#fff;--surface-soft:#f3f7f5;--line:#d7e3df;--control-line:#748b82;--text:#18312c;--muted:#58736b;--accent:#176e5e;--accent-strong:#075743;--accent-tint:#dff4e9;--focus:#966000;--warn:#76510d;--warn-bg:#fff6df;--error:#a73434;--error-bg:#fff0ec;--shadow:0 18px 50px #1e403414;font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}:root:not([data-theme=light]){--page:#0d1716;--side:#10201d;--side-line:#294a41;--side-text:#eaf7f1;--surface:#182722;--surface-soft:#20342d;--line:#355247;--control-line:#688f7f;--text:#eaf5ee;--muted:#adccbc;--accent:#7ed6ac;--accent-strong:#a4edc2;--accent-tint:#234b38;--focus:#ffca6a;--warn:#ffdd8a;--warn-bg:#463b21;--error:#ffc0b7;--error-bg:#4a2b2a;--shadow:0 18px 50px #00000024}}:root[data-theme=dark]{--page:#0d1716;--side:#10201d;--side-line:#294a41;--side-text:#eaf7f1;--surface:#182722;--surface-soft:#20342d;--line:#355247;--control-line:#688f7f;--text:#eaf5ee;--muted:#adccbc;--accent:#7ed6ac;--accent-strong:#a4edc2;--accent-tint:#234b38;--focus:#ffca6a;--warn:#ffdd8a;--warn-bg:#463b21;--error:#ffc0b7;--error-bg:#4a2b2a;--shadow:0 18px 50px #00000024}:root[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}:root[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}body{background:var(--page);color:var(--text);margin:0}button,input,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.5}:focus-visible{outline:3px solid var(--focus);outline-offset:3px}.visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}a{color:var(--accent-strong);text-underline-offset:3px}.card,.context-card{background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow);border-radius:15px}.primary{border:1px solid var(--accent-strong);background:var(--accent-strong);color:var(--side);border-radius:8px;min-height:43px;padding:12px 18px;font-size:12px;font-weight:800}:root[data-theme=light] .primary,:root:not([data-theme=dark]) .primary{color:#fff}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .primary{color:#0d2419}}.primary span{margin-left:18px}.primary:hover:not(:disabled){filter:brightness(1.1)}.secondary{border:1px solid var(--control-line);color:var(--text);background:var(--surface-soft);border-radius:8px;padding:11px 16px;font-size:12px;font-weight:700}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important}}.shell{grid-template-columns:minmax(250px,288px) minmax(0,1fr);min-height:100vh;display:grid}.sidebar{background:var(--side);color:var(--side-text);flex-direction:column;min-height:100vh;padding:34px 28px;display:flex;position:sticky;top:0}.brand{letter-spacing:-.035em;align-items:center;gap:13px;display:flex}.brand-mark{color:#0c3021;background:#75d9a0;border-radius:11px;place-items:center;width:37px;height:37px;font-size:26px;line-height:1;display:grid}.brand strong{font-size:23px;line-height:1;display:block}.brand small{letter-spacing:.23em;color:#aac8bd;margin-top:5px;font-size:9px;font-weight:800;display:block}.rail-caption{color:#9dbab0;letter-spacing:.18em;margin-block:78px 22px;margin-inline-start:7px;font-size:10px;font-weight:800}.sidebar .description{color:#afcabe}.steps{margin:0;padding:0;list-style:none;position:relative}.steps:before{content:"";top:22px;bottom:22px;background:var(--side-line);width:1px;position:absolute;inset-inline-start:19px}.steps li{color:#a6c2b7;border-radius:10px;align-items:center;gap:16px;min-height:55px;padding-block:8px;padding-inline:1px 12px;font-size:13px;font-weight:600;display:flex;position:relative}.steps li.current{color:#fff;background:#25443b}.steps li.completed{color:#dbf2e4}.step-index{border:1px solid var(--side-line);background:var(--side);letter-spacing:.04em;border-radius:50%;flex:0 0 37px;place-items:center;height:37px;font-size:11px;font-weight:800;display:grid}.steps .current .step-index{color:#102b1d;background:#80dba8;border-color:#80dba8}.steps .completed .step-index{color:#b9f8c9;background:#204c37;border-color:#45966b;font-size:15px}.sidebar-note{border:1px solid var(--side-line);background:#ffffff09;border-radius:13px;gap:13px;margin-top:auto;padding:19px 16px;display:flex}.sidebar-note>span{color:#8fe1ae;font-size:20px}.sidebar-note strong{font-size:12px}.sidebar-note p{color:#afcabe;margin:6px 0 0;font-size:11px;line-height:1.6}.main{min-width:0}.topbar{border-bottom:1px solid var(--line);background:var(--surface);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;min-height:80px;padding:20px clamp(24px,4vw,70px);display:flex}.breadcrumb{flex:240px;align-items:center;gap:12px;min-width:0;font-size:12px;display:flex}.breadcrumb span:first-child{color:var(--muted);letter-spacing:.14em;font-size:10px;font-weight:800}.breadcrumb span:nth-child(2){color:var(--muted)}.breadcrumb strong{white-space:normal;overflow-wrap:anywhere;min-width:0;line-height:1.5}.top-actions{flex-shrink:0;align-items:center;gap:18px;display:flex}.local-pill{color:var(--accent-strong);background:var(--accent-tint);letter-spacing:.08em;white-space:nowrap;border-radius:6px;padding:8px 11px;font-size:10px;font-weight:800}.pulse-dot{background:currentColor;border-radius:50%;width:6px;height:6px;margin-right:5px;display:inline-block}.theme-switch{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;padding:3px;display:flex}.theme-switch button{color:var(--muted);background:0 0;border:0;border-radius:5px;min-width:31px;height:27px;font-size:11px}.theme-switch button.active{background:var(--surface);color:var(--text);font-weight:800;box-shadow:0 1px 4px #0000001f}.content{max-width:1320px;margin:0 auto;padding:52px clamp(24px,4vw,70px) 35px}.eyebrow{color:var(--accent-strong);letter-spacing:.18em;align-items:center;gap:10px;font-size:10px;font-weight:900;display:flex}.eyebrow-line{background:var(--accent);width:21px;height:2px}.eyebrow-count{color:var(--muted);letter-spacing:.09em;margin-inline-start:8px}h1{letter-spacing:-.045em;max-width:860px;margin:15px 0 13px;font-size:clamp(30px,3vw,45px);line-height:1.15}.lede{color:var(--muted);max-width:700px;margin:0 0 30px;font-size:14px;line-height:1.65}.workspace-grid{grid-template-columns:minmax(0,1.65fr) minmax(230px,.8fr);align-items:start;gap:19px;display:grid}.workspace-grid:has(.plan-review){grid-template-columns:1fr}.workspace-grid:has(.plan-review) .context-column{grid-template-columns:repeat(2,minmax(0,1fr))}.context-column{gap:17px;display:grid}.context-card{box-shadow:none;padding:25px}.context-icon{background:var(--accent-tint);width:32px;height:32px;color:var(--accent-strong);border-radius:8px;place-items:center;font-size:19px;display:grid}.context-card h2{letter-spacing:-.015em;margin:17px 0 7px;font-size:14px}.context-card p,.context-card>small{color:var(--muted);margin:0 0 12px;font-size:12px;line-height:1.65;display:block}.context-card code{background:var(--surface-soft);overflow-wrap:anywhere;border-radius:6px;padding:10px;font-size:11px;display:block}.permissions ul{margin:8px 0 13px;padding:0;list-style:none}.permissions li{border-bottom:1px solid var(--line);justify-content:space-between;gap:10px;padding:9px 0;font-size:11px;display:flex}.permissions li small{color:var(--muted);margin-top:3px;display:block}.permissions li strong{color:var(--accent-strong);text-transform:uppercase;font-size:9px}.permission-progress{padding:clamp(20px,4vw,38px)}.permission-progress h2{margin:0 0 8px}.permission-progress p{color:var(--muted);line-height:1.5}.permission-progress ol{margin:20px 0 0;padding:0;list-style:none}.permission-progress li{border-top:1px solid var(--line);align-items:center;gap:14px;padding:12px 0;display:flex}.permission-progress li>span:nth-child(2){flex:1;min-width:0}.permission-progress li small{color:var(--muted);overflow-wrap:anywhere;display:block}.permission-progress-symbol{background:var(--surface-soft);border-radius:50%;flex:none;place-items:center;width:30px;height:30px;display:grid}.permission-progress-done .permission-progress-symbol{color:var(--accent-strong)}.permission-progress-failed .permission-progress-symbol{color:var(--danger,#a33)}.permission-progress-state{text-align:right;max-width:35%;font-size:.8rem;font-weight:600}@media (width<=600px){.permission-progress li{flex-wrap:wrap;align-items:flex-start}.permission-progress-state{text-align:left;max-width:none;margin-left:44px}}footer{color:var(--muted);opacity:.85;letter-spacing:.11em;margin-top:40px;font-size:9px;font-weight:700}footer span{margin:0 8px}[dir=rtl] .context-card code,[dir=rtl] .result-links code,[dir=rtl] .producer-option strong,[dir=rtl] .producer-option small,[dir=rtl] input[type=password]{direction:ltr;unicode-bidi:isolate}.decision-card{min-height:360px;padding:clamp(25px,3vw,40px)}.card-header{justify-content:space-between;align-items:center;gap:12px;margin-bottom:29px;display:flex}.card-kicker{color:var(--accent-strong);letter-spacing:.17em;font-size:10px;font-weight:900}.revision{color:var(--muted);letter-spacing:.08em;font-size:10px}.description{white-space:pre-line;color:var(--muted);margin-top:0;font-size:13px;line-height:1.65}.question-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:10px;margin-bottom:15px;display:flex}.question-heading h2,.decision-card>label{margin:0 0 10px;font-size:15px;font-weight:700;line-height:1.4;display:block}.phase-tag{color:var(--accent-strong);background:var(--accent-tint);letter-spacing:.07em;border-radius:5px;padding:6px 8px;font-size:9px;font-weight:900}input[type=text],input[type=password],input[type=number],select{border:1px solid var(--control-line);background:var(--surface-soft);width:100%;min-height:46px;color:var(--text);border-radius:8px;padding:10px 13px}textarea{resize:vertical;border:1px solid var(--control-line);background:var(--surface-soft);width:100%;min-height:120px;color:var(--text);font:inherit;border-radius:8px;padding:12px 13px;line-height:1.5}.language-switch{color:var(--muted);white-space:nowrap;align-items:center;gap:7px;font-size:11px;font-weight:700;display:flex}.language-switch select{width:auto;max-width:140px;min-height:32px;padding:5px 8px;font-size:11px}.question-details{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin-bottom:20px;padding:13px 15px;font-size:12px}.question-details summary{cursor:pointer;color:var(--accent-strong);font-weight:800}.question-details dl{grid-template-columns:minmax(90px,130px) minmax(0,1fr);gap:10px 14px;margin:14px 0 0;line-height:1.55;display:grid}.question-details dt{color:var(--text);font-weight:750}.question-details dd{color:var(--muted);margin:0}.question-help-link{margin:-12px 0 18px;font-size:12px;font-weight:700}.discovery-actions{flex-wrap:wrap;align-items:center;gap:8px 14px;margin:4px 0 16px;display:flex}.discovery-actions .field-help{margin:0}.secondary-button{border:1px solid var(--control-line);background:var(--surface-soft);color:var(--accent-strong);font:inherit;border-radius:8px;padding:9px 13px;font-size:12px;font-weight:750}.secondary-button:hover:not(:disabled),.secondary-button:focus-visible{border-color:var(--accent);background:var(--accent-tint)}.secondary-button:disabled{opacity:.55;cursor:not-allowed}.status-review-list{color:var(--muted);margin:6px 0 18px;padding-inline-start:20px;font-size:12px;line-height:1.7}.status-review-list strong{color:var(--text)}.producer-grid{margin-bottom:20px;padding:6px}.check-option.producer-option{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:16px;padding:14px 16px;display:grid}.producer-option>label{cursor:pointer;align-items:flex-start;gap:12px;min-width:0;display:flex}.producer-option>label>input{flex:0 0 17px;margin:3px 0 0}.producer-option>label>span{overflow-wrap:anywhere;gap:5px;min-width:0;display:grid}.producer-option small{color:var(--muted);font-size:10px;line-height:1.5}.producer-option a{font-size:11px;line-height:1.5}.producer-option>a{max-width:140px}.producer-links{gap:8px;max-width:140px;display:grid}.producer-manual-fields{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.producer-manual-fields>label,.project-manual-field{gap:8px;font-size:12px;font-weight:700;line-height:1.5;display:grid}.producer-manual-fields>label:last-child{grid-column:1/-1}.producer-add{margin-top:16px}.project-manual-field{margin-top:20px}input[type=checkbox]{accent-color:var(--accent);width:17px;height:17px}.field-help{color:var(--muted);margin:14px 0 24px;font-size:12px;line-height:1.6}.segmented{gap:9px;display:flex}.segmented button{border:1px solid var(--control-line);color:var(--text);background:var(--surface-soft);border-radius:8px;flex:1;padding:13px;font-weight:700}.segmented button.selected{border-color:var(--accent);background:var(--accent-tint);color:var(--accent-strong)}.check-grid{gap:10px;display:grid}.check-option{background:var(--surface-soft);border:1px solid var(--control-line);border-radius:7px;align-items:center;gap:10px;padding:10px 13px;font-size:12px;display:flex}.choice-list{gap:9px;display:grid}.choice-card{text-align:left;background:var(--surface-soft);width:100%;min-height:52px;color:var(--text);border:1px solid var(--control-line);border-radius:8px;justify-content:space-between;align-items:center;padding:13px 15px;font-size:13px;font-weight:650;display:flex}.choice-card:hover:not(:disabled){border-color:var(--accent);background:var(--accent-tint)}.github-link{background:var(--accent-tint);border:1px solid var(--accent);border-radius:8px;margin:0 0 12px;padding:14px;font-size:13px;font-weight:800;text-decoration:none;display:block}.github-link span{float:right}.plan-review{gap:24px;font-size:12px;line-height:1.65;display:grid}.plan-review>.description,.plan-review .field-help{margin:0}.plan-sections{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:16px;display:grid}.plan-decisions,.plan-inventory,.plan-warnings{background:var(--surface-soft);border:1px solid var(--line);border-radius:8px;min-width:0;padding:20px}.plan-decisions h3,.plan-warnings h3{margin:0 0 14px;font-size:13px;line-height:1.5}.plan-decisions p{margin:0 0 16px}.plan-decisions>:last-child{margin-bottom:0}.plan-decisions dl{gap:0;margin:0;display:grid}.plan-decisions dl>div{border-bottom:1px solid var(--line);grid-template-columns:minmax(130px,35%) minmax(0,1fr);gap:20px;padding:12px 0;display:grid}.plan-decisions dl>div:first-child{padding-top:0}.plan-decisions dl>div:last-child{border-bottom:0;padding-bottom:0}.plan-decisions dt{color:var(--muted)}.plan-decisions dd{overflow-wrap:anywhere;min-width:0;margin:0}.plan-decisions .field-help{margin-top:20px}.plan-decisions ul,.plan-inventory ul,.plan-warnings ul{overflow-wrap:anywhere;margin:0;padding-inline-start:20px;font-size:12px;line-height:1.7}.plan-decisions li+li,.plan-inventory li+li,.plan-warnings li+li{margin-top:6px}.plan-inventory summary{cursor:pointer;font-size:13px;font-weight:750}.plan-inventory summary span:last-child{float:right;color:var(--accent-strong);margin-inline-start:12px}.plan-inventory[open] summary{margin-bottom:16px}.plan-warnings{color:var(--warn);background:var(--warn-bg)}.plan-edit{border-top:1px solid var(--line);padding-top:24px}.plan-edit h3{margin:0 0 4px;font-size:14px}.plan-edit-actions{flex-wrap:wrap;gap:10px;margin-top:16px;display:flex}.button-row{flex-wrap:wrap;align-items:center;gap:12px;margin-top:24px;display:flex}.button-row>.primary{margin-left:auto}.plan-review>.button-row{border-top:1px solid var(--line);margin-top:0;padding-top:24px}.review-pass,.banner{white-space:pre-line;border-radius:8px;margin:0 0 20px;padding:14px 18px;font-size:12px;line-height:1.5}.review-pass{color:var(--accent-strong);background:var(--accent-tint);border:1px solid var(--accent)}.review-pass span{margin-inline-end:8px;font-weight:800}.banner{background:var(--surface-soft);border:1px solid var(--line)}.banner p{margin:5px 0 0}.banner.warning{color:var(--warn);background:var(--warn-bg);border-color:var(--warn)}.banner.error{color:var(--error);background:var(--error-bg);border-color:var(--error)}.banner.success{color:var(--accent-strong);background:var(--accent-tint);border-color:var(--accent)}.banner button{margin-top:12px}.cancel-link{color:var(--muted);background:0 0;border:0;margin-top:18px;padding:5px 0;font-size:12px;text-decoration:underline}.result-card,.waiting-card{max-width:750px;padding:36px}.result-icon{background:var(--accent-tint);width:43px;height:43px;color:var(--accent-strong);border-radius:50%;place-items:center;font-size:22px;display:grid}.result-card h2,.waiting-card h2{margin:18px 0 10px;font-size:21px}.result-card p,.waiting-card p{color:var(--muted);font-size:13px;line-height:1.6}.result-facts{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin:24px 0;padding:20px}.result-facts p{margin:8px 0}.result-facts strong{color:var(--text)}.result-effects{border:1px solid var(--line);background:var(--surface-soft);border-radius:8px;margin:20px 0;padding:14px 17px}.result-effects h3{color:var(--text);margin:0 0 10px;font-size:13px}.result-effects ul{margin:0;padding-left:20px}.result-effects li{overflow-wrap:anywhere;padding:3px 0;font-size:12px}.result-links{flex-wrap:wrap;align-items:center;gap:20px;margin:22px 0;font-size:12px;display:flex}.result-links code{background:var(--surface-soft);border-radius:5px;padding:8px}.spinner{border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;width:25px;height:25px;animation:1s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.result-facts h3{margin:0 0 16px;font-size:15px;line-height:1.5}.result-permissions{margin:20px 0 0;padding-inline-start:20px;font-size:13px;line-height:1.65}.result-permissions li+li{margin-top:16px}.result-permissions p{margin:6px 0 0}@media (width<=1100px){.workspace-grid{grid-template-columns:1fr}.context-column{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=780px){.shell{display:block}.sidebar{min-height:0;padding:16px 20px;position:static}.rail-caption,.sidebar-note{display:none}.steps{flex-wrap:wrap;gap:4px;margin-top:18px;display:flex}.steps:before{display:none}.steps li{flex:none;gap:6px;min-height:37px;padding:4px 7px;font-size:11px}.step-index{flex-basis:26px;width:26px;height:26px}.topbar{flex-wrap:wrap;height:auto;min-height:65px;padding:12px 20px}.content{padding:28px 20px}}@media (width<=540px){.context-column,.plan-sections{grid-template-columns:1fr}.workspace-grid:has(.plan-review) .context-column{grid-template-columns:1fr}.top-actions{flex-wrap:wrap;justify-content:space-between;gap:12px;width:100%;min-width:0}.decision-card{padding:22px}.breadcrumb{max-width:100%}h1{font-size:29px}.plan-decisions dl>div{grid-template-columns:1fr;gap:2px}.question-details dl{grid-template-columns:1fr;gap:3px}.question-details dd{margin-bottom:9px}.language-switch{margin-inline-start:auto}}@media (width<=640px){.check-option.producer-option{grid-template-columns:minmax(0,1fr);gap:12px}.producer-option>a,.producer-links{max-width:none;margin-inline-start:29px}.producer-manual-fields{grid-template-columns:minmax(0,1fr)}}.management-status{color:var(--accent-strong);font-weight:750}.management-actions{flex-wrap:wrap;gap:12px;margin-block:24px 32px;display:flex}.management-section{border-top:1px solid var(--line);padding-block:26px}.management-section h2{margin-top:0}.management-section summary{cursor:pointer;color:var(--accent-strong);font-weight:700}.management-settings{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;display:grid}.management-setting{border:1px solid var(--line);background:var(--surface-soft);border-radius:10px;justify-content:space-between;align-items:center;gap:16px;padding:18px;display:flex}.management-setting h3{margin:0 0 8px;font-size:14px}.management-setting p{color:var(--muted);overflow-wrap:anywhere;margin:0}.management-setting .button{flex-shrink:0}.management-values{gap:8px;display:grid}.management-values dt{overflow-wrap:anywhere;margin-top:12px;font-weight:650}.management-values dd{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--muted);margin:0;line-height:1.6}.management-workflow{padding-block:16px}:is(.workspace-grid:has(.management-settings),.workspace-grid:has(.management-status)){grid-template-columns:1fr}.workspace-grid:has(.management-status) .context-column{display:none}@media (width<=800px){.management-settings{grid-template-columns:1fr}}@media (width<=420px){.management-setting{flex-direction:column;align-items:stretch}.management-setting .button{align-self:flex-end}}