diff --git a/.github/workflows/copilot_comment_runtime.yml b/.github/workflows/copilot_comment_runtime.yml new file mode 100644 index 000000000..b17c4d3a3 --- /dev/null +++ b/.github/workflows/copilot_comment_runtime.yml @@ -0,0 +1,738 @@ +# Generated by scripts/generate-native-verification-workflows.cjs +name: Copilot - Comment Runtime +'on': + workflow_call: + inputs: + runs-on: + description: JSON runner labels or group retained by setup. + type: string + default: '"ubuntu-latest"' + issue-managed-branches: + description: Optional issue-managed-branches override; otherwise use the caller repository Variable. + type: string + default: '' + pre-branch-sdd: + description: Optional pre-branch-sdd override; otherwise use the caller repository Variable. + type: string + default: '' + ai-ignore-files: + description: Optional ai-ignore-files override; otherwise use the caller repository Variable. + type: string + default: '' + prepare-source-verification: + description: Retain Copilot source-repository verification prerequisites; ignored in consumer repositories. + type: boolean + default: false + secrets: + PAT: + required: false + OPENCODE_API_KEY: + required: false + OPENAI_API_KEY: + required: false + ANTHROPIC_API_KEY: + required: false + GOOGLE_API_KEY: + required: false + OPENROUTER_API_KEY: + required: false + CURSOR_API_KEY: + required: false + CODEX_API_KEY: + required: false +jobs: + copilot: + name: Copilot + if: ${{ (vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN) && (github.event_name == 'issue_comment' || (github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.full_name == github.repository)) }} + runs-on: ${{ fromJSON(inputs.runs-on) }} + timeout-minutes: 120 + permissions: + checks: write + contents: read + env: + COPILOT_PREPARE_VERIFICATION: ${{ github.repository == 'vypdev/copilot' && inputs.prepare-source-verification && vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS != '' && ((contains(github.event.comment.body, '/copilot') && ((contains(github.event.comment.body, 'sync-branch') && !contains(github.event.comment.body, '--dry-run')) || contains(github.event.comment.body, 'implement') || contains(github.event.comment.body, 'fix') || contains(github.event.comment.body, 'remember'))) || (vars.COPILOT_BOT_LOGIN != '' && contains(github.event.comment.body, format('@{0}', vars.COPILOT_BOT_LOGIN)) && !contains(github.event.comment.body, '--dry-run'))) }} + steps: + - name: Checkout Repository + uses: actions/checkout@v5 + with: + persist-credentials: false + fetch-depth: 0 + - name: Prepare repository pnpm + if: env.COPILOT_PREPARE_VERIFICATION == 'true' + uses: pnpm/action-setup@v5 + with: + version: 10.12.4 + standalone: false + dest: ${{ runner.temp }}/setup-pnpm-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }} + - name: Prepare repository Node + if: env.COPILOT_PREPARE_VERIFICATION == 'true' + uses: actions/setup-node@v7 + with: + node-version: 24.x + - name: Install repository verification dependencies + if: env.COPILOT_PREPARE_VERIFICATION == 'true' + run: pnpm install --frozen-lockfile --ignore-scripts + shell: bash + - name: Run Copilot + id: copilot + uses: $/ + with: &ref_0 + repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }} + issues-locale: ${{ vars.ISSUES_LOCALE || '' }} + pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }} + ai-ignore-files: ${{ inputs.ai-ignore-files || vars.AI_IGNORE_FILES || 'build/*' }} + debug: ${{ vars.DEBUG }} + main-branch: ${{ vars.MAIN_BRANCH || 'master' }} + development-branch: ${{ vars.DEVELOPMENT_BRANCH || 'develop' }} + feature-tree: ${{ vars.FEATURE_TREE || 'feature' }} + bugfix-tree: ${{ vars.BUGFIX_TREE || 'bugfix' }} + hotfix-tree: ${{ vars.HOTFIX_TREE || 'hotfix' }} + release-tree: ${{ vars.RELEASE_TREE || 'release' }} + docs-tree: ${{ vars.DOCS_TREE || 'docs' }} + chore-tree: ${{ vars.CHORE_TREE || 'chore' }} + issue-managed-branches: ${{ inputs.issue-managed-branches || vars.ISSUE_MANAGED_BRANCHES || 'true' }} + pre-branch-sdd: ${{ inputs.pre-branch-sdd || vars.PRE_BRANCH_SDD || 'false' }} + verification-setup: ${{ vars.VERIFICATION_SETUP || 'false' }} + issue-workflow-profile: ${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }} + reopen-issue-on-push: ${{ vars.REOPEN_ISSUE_ON_PUSH || 'true' }} + desired-assignees-count: ${{ vars.DESIRED_ASSIGNEES_COUNT || '1' }} + desired-reviewers-count: ${{ vars.DESIRED_REVIEWERS_COUNT || '1' }} + commit-prefix-transforms: ${{ vars.COMMIT_PREFIX_TRANSFORMS || 'replace-slash' }} + ai-pull-request-description-mode: ${{ vars.AI_PULL_REQUEST_DESCRIPTION_MODE || 'replace' }} + ai-members-only: ${{ vars.AI_MEMBERS_ONLY || 'false' }} + ai-include-reasoning: ${{ vars.AI_INCLUDE_REASONING || 'false' }} + bugbot-severity: ${{ vars.BUGBOT_SEVERITY || 'low' }} + bugbot-comment-limit: ${{ vars.BUGBOT_COMMENT_LIMIT || '20' }} + bugbot-fix-verify-commands: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }} + bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }} + bugbot-effort: ${{ vars.BUGBOT_EFFORT || 'smart' }} + bugbot-review-drafts: ${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }} + bugbot-trace-rules: ${{ vars.BUGBOT_TRACE_RULES || 'false' }} + bugbot-suggested-changes: ${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }} + bugbot-telemetry: ${{ vars.BUGBOT_TELEMETRY || 'true' }} + bugbot-fail-on-unresolved: ${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }} + bugbot-organization-rules: ${{ vars.BUGBOT_ORGANIZATION_RULES }} + project-column-issue-created: ${{ vars.PROJECT_COLUMN_ISSUE_CREATED || 'Todo' }} + project-column-pull-request-created: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_CREATED || 'In Progress' }} + project-column-issue-in-progress: ${{ vars.PROJECT_COLUMN_ISSUE_IN_PROGRESS || 'In Progress' }} + project-column-pull-request-in-progress: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_IN_PROGRESS || 'In Progress' }} + agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }} + agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} + agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }} + agent-effort: ${{ vars.AGENT_EFFORT }} + agent-executable: ${{ vars.AGENT_EXECUTABLE }} + findings-provider: ${{ vars.FINDINGS_PROVIDER }} + findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }} + findings-model: ${{ vars.FINDINGS_MODEL }} + findings-effort: ${{ vars.FINDINGS_EFFORT }} + findings-executable: ${{ vars.FINDINGS_EXECUTABLE }} + fixer-provider: ${{ vars.FIXER_PROVIDER }} + fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }} + fixer-model: ${{ vars.FIXER_MODEL }} + fixer-effort: ${{ vars.FIXER_EFFORT }} + fixer-executable: ${{ vars.FIXER_EXECUTABLE }} + planner-provider: ${{ vars.PLANNER_PROVIDER }} + planner-model-provider: ${{ vars.PLANNER_MODEL_PROVIDER }} + planner-model: ${{ vars.PLANNER_MODEL }} + planner-effort: ${{ vars.PLANNER_EFFORT }} + planner-executable: ${{ vars.PLANNER_EXECUTABLE }} + reviewer-provider: ${{ vars.REVIEWER_PROVIDER }} + reviewer-model-provider: ${{ vars.REVIEWER_MODEL_PROVIDER }} + reviewer-model: ${{ vars.REVIEWER_MODEL }} + reviewer-effort: ${{ vars.REVIEWER_EFFORT }} + reviewer-executable: ${{ vars.REVIEWER_EXECUTABLE }} + tester-provider: ${{ vars.TESTER_PROVIDER }} + tester-model-provider: ${{ vars.TESTER_MODEL_PROVIDER }} + tester-model: ${{ vars.TESTER_MODEL }} + tester-effort: ${{ vars.TESTER_EFFORT }} + tester-executable: ${{ vars.TESTER_EXECUTABLE }} + project-ids: ${{ vars.PROJECT_IDS }} + token: ${{ secrets.PAT }} + env: + COPILOT_NATIVE_PHASE: prepare + AGENT_PROVIDER: ${{ vars.AGENT_PROVIDER || 'codex' }} + AGENT_MODEL_PROVIDER: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} + AGENT_MODEL: ${{ vars.AGENT_MODEL }} + AGENT_EFFORT: ${{ vars.AGENT_EFFORT }} + AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }} + AGENT_ALLOWED_MODEL_PROVIDERS: ${{ vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai' }} + AGENT_ALLOWED_MODELS: ${{ vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna' }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + CURSOR_API_KEY: ${{ (vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || '' }} + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} + COPILOT_EVIDENCE_TOKEN: ${{ github.token }} + - name: Prepare repository verification 1 + id: verification_setup_1 + if: ${{ !cancelled() && steps.copilot.outcome == 'success' && steps.copilot.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.copilot.outputs.verification-home }} + USERPROFILE: ${{ steps.copilot.outputs.verification-userprofile }} + APPDATA: ${{ steps.copilot.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.copilot.outputs.verification-localappdata }} + PATH: ${{ steps.copilot.outputs.verification-path }} + JAVA_HOME: ${{ steps.copilot.outputs.verification-java_home }} + TMP: ${{ steps.copilot.outputs.verification-tmp }} + TEMP: ${{ steps.copilot.outputs.verification-temp }} + TMPDIR: ${{ steps.copilot.outputs.verification-tmpdir }} + - name: Continue repository verification 1 + id: verification_continue_1 + if: ${{ always() && steps.copilot.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.copilot.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_1.outcome }} + - name: Prepare repository verification 2 + id: verification_setup_2 + if: ${{ !cancelled() && steps.verification_continue_1.outcome == 'success' && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_1.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_1.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_1.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_1.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_1.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_1.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_1.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_1.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_1.outputs.verification-tmpdir }} + - name: Continue repository verification 2 + id: verification_continue_2 + if: ${{ always() && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_1.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_2.outcome }} + - name: Prepare repository verification 3 + id: verification_setup_3 + if: ${{ !cancelled() && steps.verification_continue_2.outcome == 'success' && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_2.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_2.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_2.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_2.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_2.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_2.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_2.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_2.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_2.outputs.verification-tmpdir }} + - name: Continue repository verification 3 + id: verification_continue_3 + if: ${{ always() && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_2.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_3.outcome }} + - name: Prepare repository verification 4 + id: verification_setup_4 + if: ${{ !cancelled() && steps.verification_continue_3.outcome == 'success' && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_3.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_3.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_3.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_3.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_3.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_3.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_3.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_3.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_3.outputs.verification-tmpdir }} + - name: Continue repository verification 4 + id: verification_continue_4 + if: ${{ always() && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_3.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_4.outcome }} + - name: Prepare repository verification 5 + id: verification_setup_5 + if: ${{ !cancelled() && steps.verification_continue_4.outcome == 'success' && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_4.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_4.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_4.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_4.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_4.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_4.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_4.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_4.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_4.outputs.verification-tmpdir }} + - name: Continue repository verification 5 + id: verification_continue_5 + if: ${{ always() && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_4.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_5.outcome }} + - name: Prepare repository verification 6 + id: verification_setup_6 + if: ${{ !cancelled() && steps.verification_continue_5.outcome == 'success' && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_5.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_5.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_5.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_5.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_5.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_5.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_5.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_5.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_5.outputs.verification-tmpdir }} + - name: Continue repository verification 6 + id: verification_continue_6 + if: ${{ always() && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_5.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_6.outcome }} + - name: Prepare repository verification 7 + id: verification_setup_7 + if: ${{ !cancelled() && steps.verification_continue_6.outcome == 'success' && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_6.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_6.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_6.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_6.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_6.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_6.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_6.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_6.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_6.outputs.verification-tmpdir }} + - name: Continue repository verification 7 + id: verification_continue_7 + if: ${{ always() && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_6.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_7.outcome }} + - name: Prepare repository verification 8 + id: verification_setup_8 + if: ${{ !cancelled() && steps.verification_continue_7.outcome == 'success' && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_7.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_7.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_7.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_7.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_7.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_7.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_7.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_7.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_7.outputs.verification-tmpdir }} + - name: Continue repository verification 8 + id: verification_continue_8 + if: ${{ always() && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_7.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_8.outcome }} + - name: Prepare repository verification 9 + id: verification_setup_9 + if: ${{ !cancelled() && steps.verification_continue_8.outcome == 'success' && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_8.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_8.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_8.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_8.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_8.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_8.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_8.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_8.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_8.outputs.verification-tmpdir }} + - name: Continue repository verification 9 + id: verification_continue_9 + if: ${{ always() && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_8.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_9.outcome }} + - name: Prepare repository verification 10 + id: verification_setup_10 + if: ${{ !cancelled() && steps.verification_continue_9.outcome == 'success' && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_9.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_9.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_9.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_9.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_9.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_9.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_9.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_9.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_9.outputs.verification-tmpdir }} + - name: Continue repository verification 10 + id: verification_continue_10 + if: ${{ always() && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_9.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_10.outcome }} + - name: Prepare repository verification 11 + id: verification_setup_11 + if: ${{ !cancelled() && steps.verification_continue_10.outcome == 'success' && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_10.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_10.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_10.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_10.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_10.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_10.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_10.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_10.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_10.outputs.verification-tmpdir }} + - name: Continue repository verification 11 + id: verification_continue_11 + if: ${{ always() && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_10.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_11.outcome }} + - name: Prepare repository verification 12 + id: verification_setup_12 + if: ${{ !cancelled() && steps.verification_continue_11.outcome == 'success' && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_11.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_11.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_11.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_11.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_11.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_11.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_11.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_11.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_11.outputs.verification-tmpdir }} + - name: Continue repository verification 12 + id: verification_continue_12 + if: ${{ always() && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_11.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_12.outcome }} + - name: Prepare repository verification 13 + id: verification_setup_13 + if: ${{ !cancelled() && steps.verification_continue_12.outcome == 'success' && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_12.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_12.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_12.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_12.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_12.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_12.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_12.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_12.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_12.outputs.verification-tmpdir }} + - name: Continue repository verification 13 + id: verification_continue_13 + if: ${{ always() && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_12.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_13.outcome }} + - name: Prepare repository verification 14 + id: verification_setup_14 + if: ${{ !cancelled() && steps.verification_continue_13.outcome == 'success' && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_13.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_13.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_13.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_13.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_13.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_13.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_13.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_13.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_13.outputs.verification-tmpdir }} + - name: Continue repository verification 14 + id: verification_continue_14 + if: ${{ always() && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_13.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_14.outcome }} + - name: Prepare repository verification 15 + id: verification_setup_15 + if: ${{ !cancelled() && steps.verification_continue_14.outcome == 'success' && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_14.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_14.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_14.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_14.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_14.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_14.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_14.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_14.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_14.outputs.verification-tmpdir }} + - name: Continue repository verification 15 + id: verification_continue_15 + if: ${{ always() && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_14.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_15.outcome }} + - name: Prepare repository verification 16 + id: verification_setup_16 + if: ${{ !cancelled() && steps.verification_continue_15.outcome == 'success' && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_15.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_15.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_15.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_15.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_15.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_15.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_15.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_15.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_15.outputs.verification-tmpdir }} + - name: Continue repository verification 16 + id: verification_continue_16 + if: ${{ always() && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_15.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_16.outcome }} + - name: Prepare repository verification 17 + id: verification_setup_17 + if: ${{ !cancelled() && steps.verification_continue_16.outcome == 'success' && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_16.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_16.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_16.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_16.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_16.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_16.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_16.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_16.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_16.outputs.verification-tmpdir }} + - name: Continue repository verification 17 + id: verification_continue_17 + if: ${{ always() && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_16.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_17.outcome }} + - name: Prepare repository verification 18 + id: verification_setup_18 + if: ${{ !cancelled() && steps.verification_continue_17.outcome == 'success' && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_17.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_17.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_17.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_17.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_17.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_17.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_17.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_17.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_17.outputs.verification-tmpdir }} + - name: Continue repository verification 18 + id: verification_continue_18 + if: ${{ always() && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_17.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_18.outcome }} + - name: Prepare repository verification 19 + id: verification_setup_19 + if: ${{ !cancelled() && steps.verification_continue_18.outcome == 'success' && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_18.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_18.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_18.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_18.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_18.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_18.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_18.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_18.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_18.outputs.verification-tmpdir }} + - name: Continue repository verification 19 + id: verification_continue_19 + if: ${{ always() && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_18.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_19.outcome }} + - name: Prepare repository verification 20 + id: verification_setup_20 + if: ${{ !cancelled() && steps.verification_continue_19.outcome == 'success' && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} + uses: ./.git/copilot-verification-setup + timeout-minutes: 5 + env: + HOME: ${{ steps.verification_continue_19.outputs.verification-home }} + USERPROFILE: ${{ steps.verification_continue_19.outputs.verification-userprofile }} + APPDATA: ${{ steps.verification_continue_19.outputs.verification-appdata }} + LOCALAPPDATA: ${{ steps.verification_continue_19.outputs.verification-localappdata }} + PATH: ${{ steps.verification_continue_19.outputs.verification-path }} + JAVA_HOME: ${{ steps.verification_continue_19.outputs.verification-java_home }} + TMP: ${{ steps.verification_continue_19.outputs.verification-tmp }} + TEMP: ${{ steps.verification_continue_19.outputs.verification-temp }} + TMPDIR: ${{ steps.verification_continue_19.outputs.verification-tmpdir }} + - name: Continue repository verification 20 + id: verification_continue_20 + if: ${{ always() && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: continue + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} + COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_19.outputs.verification-request }} + COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_20.outcome }} + - name: Complete repository verification + id: verification_complete + if: ${{ always() && steps.copilot.outputs.verification-ticket != '' }} + uses: $/ + with: *ref_0 + env: + COPILOT_NATIVE_PHASE: finish + COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} + COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} + COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} + COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} diff --git a/.github/workflows/copilot_issue_comment.yml b/.github/workflows/copilot_issue_comment.yml index b8a567d2d..2cc07d44c 100644 --- a/.github/workflows/copilot_issue_comment.yml +++ b/.github/workflows/copilot_issue_comment.yml @@ -1,694 +1,32 @@ +# Generated by scripts/generate-native-verification-workflows.cjs +# Project runtimes: .copilot/verification-prerequisites.json +# Dependencies: .github/actions/copilot-verification-setup/action.yml +# https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites name: Copilot - Issue Comment - -on: +'on': issue_comment: - types: [created, edited] - + types: + - created + - edited jobs: copilot-issues: if: ${{ vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN }} - name: Copilot - Issue Comment - runs-on: [self-hosted, codex, Linux] - timeout-minutes: 120 + uses: $/.github/workflows/copilot_comment_runtime.yml permissions: checks: write contents: read - env: - # Preparation covers parser whitespace and mentions; authorization stays in the Action. - COPILOT_PREPARE_VERIFICATION: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS != '' && ((contains(github.event.comment.body, '/copilot') && ((contains(github.event.comment.body, 'sync-branch') && !contains(github.event.comment.body, '--dry-run')) || contains(github.event.comment.body, 'implement') || contains(github.event.comment.body, 'fix') || contains(github.event.comment.body, 'remember'))) || (vars.COPILOT_BOT_LOGIN != '' && contains(github.event.comment.body, format('@{0}', vars.COPILOT_BOT_LOGIN)) && !contains(github.event.comment.body, '--dry-run'))) }} - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Prepare repository pnpm - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - uses: pnpm/action-setup@v5 - with: - version: 10.12.4 - standalone: false - dest: ${{ runner.temp }}/setup-pnpm-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }} - - - name: Prepare repository Node - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - uses: actions/setup-node@v7 - with: - node-version: '24.x' - - - name: Install repository verification dependencies - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - shell: bash - run: pnpm install --frozen-lockfile --ignore-scripts - - - name: Snapshot the Copilot runtime before candidate changes - id: prepare_native_runtime - run: node scripts/prepare-native-source-action.cjs - shell: bash - - - uses: ./../.copilot-native-runtime - id: copilot - with: &copilot-inputs - repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }} - issues-locale: ${{ vars.ISSUES_LOCALE || '' }} - pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }} - issue-workflow-profile: ${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }} - issue-managed-branches: true - pre-branch-sdd: true - verification-setup: ${{ vars.VERIFICATION_SETUP || 'false' }} - ai-ignore-files: build/*,specs/CATALOG.md - debug: ${{ vars.DEBUG }} - agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }} - agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }} - agent-effort: ${{ vars.AGENT_EFFORT }} - agent-executable: ${{ vars.AGENT_EXECUTABLE }} - findings-provider: ${{ vars.FINDINGS_PROVIDER }} - findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }} - findings-model: ${{ vars.FINDINGS_MODEL }} - findings-effort: ${{ vars.FINDINGS_EFFORT }} - findings-executable: ${{ vars.FINDINGS_EXECUTABLE }} - fixer-provider: ${{ vars.FIXER_PROVIDER }} - fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }} - fixer-model: ${{ vars.FIXER_MODEL }} - fixer-effort: ${{ vars.FIXER_EFFORT }} - fixer-executable: ${{ vars.FIXER_EXECUTABLE }} - planner-provider: ${{ vars.PLANNER_PROVIDER }} - planner-model-provider: ${{ vars.PLANNER_MODEL_PROVIDER }} - planner-model: ${{ vars.PLANNER_MODEL }} - planner-effort: ${{ vars.PLANNER_EFFORT }} - planner-executable: ${{ vars.PLANNER_EXECUTABLE }} - reviewer-provider: ${{ vars.REVIEWER_PROVIDER }} - reviewer-model-provider: ${{ vars.REVIEWER_MODEL_PROVIDER }} - reviewer-model: ${{ vars.REVIEWER_MODEL }} - reviewer-effort: ${{ vars.REVIEWER_EFFORT }} - reviewer-executable: ${{ vars.REVIEWER_EXECUTABLE }} - tester-provider: ${{ vars.TESTER_PROVIDER }} - tester-model-provider: ${{ vars.TESTER_MODEL_PROVIDER }} - tester-model: ${{ vars.TESTER_MODEL }} - tester-effort: ${{ vars.TESTER_EFFORT }} - tester-executable: ${{ vars.TESTER_EXECUTABLE }} - project-ids: ${{ vars.PROJECT_IDS }} - token: ${{ secrets.PAT }} - bugbot-fix-verify-commands: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }} - bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }} - bugbot-effort: ${{ vars.BUGBOT_EFFORT || 'smart' }} - bugbot-review-drafts: ${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }} - bugbot-trace-rules: ${{ vars.BUGBOT_TRACE_RULES || 'false' }} - bugbot-suggested-changes: ${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }} - bugbot-telemetry: ${{ vars.BUGBOT_TELEMETRY || 'true' }} - bugbot-fail-on-unresolved: ${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }} - bugbot-organization-rules: ${{ vars.BUGBOT_ORGANIZATION_RULES }} - env: - COPILOT_NATIVE_PHASE: prepare - COPILOT_NATIVE_RUNTIME_CACHE: ${{ steps.prepare_native_runtime.outputs.path }} - AGENT_PROVIDER: ${{ vars.AGENT_PROVIDER || 'codex' }} - AGENT_MODEL_PROVIDER: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - AGENT_MODEL: ${{ vars.AGENT_MODEL }} - AGENT_EFFORT: ${{ vars.AGENT_EFFORT }} - AGENT_ALLOWED_MODEL_PROVIDERS: ${{ vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai' }} - AGENT_ALLOWED_MODELS: ${{ vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna' }} - AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} - CURSOR_API_KEY: ${{ (vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || '' }} - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - COPILOT_EVIDENCE_TOKEN: ${{ github.token }} - - # copilot:native-verification:start - - name: Prepare repository verification 1 - id: verification_setup_1 - if: ${{ !cancelled() && steps.copilot.outcome == 'success' && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.copilot.outputs.verification-home }} - USERPROFILE: ${{ steps.copilot.outputs.verification-userprofile }} - APPDATA: ${{ steps.copilot.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.copilot.outputs.verification-localappdata }} - PATH: ${{ steps.copilot.outputs.verification-path }} - JAVA_HOME: ${{ steps.copilot.outputs.verification-java_home }} - TMP: ${{ steps.copilot.outputs.verification-tmp }} - TEMP: ${{ steps.copilot.outputs.verification-temp }} - TMPDIR: ${{ steps.copilot.outputs.verification-tmpdir }} - - name: Continue repository verification 1 - id: verification_continue_1 - if: ${{ always() && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.copilot.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_1.outcome }} - - name: Prepare repository verification 2 - id: verification_setup_2 - if: ${{ !cancelled() && steps.verification_continue_1.outcome == 'success' && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_1.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_1.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_1.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_1.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_1.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_1.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_1.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_1.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_1.outputs.verification-tmpdir }} - - name: Continue repository verification 2 - id: verification_continue_2 - if: ${{ always() && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_1.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_2.outcome }} - - name: Prepare repository verification 3 - id: verification_setup_3 - if: ${{ !cancelled() && steps.verification_continue_2.outcome == 'success' && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_2.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_2.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_2.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_2.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_2.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_2.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_2.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_2.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_2.outputs.verification-tmpdir }} - - name: Continue repository verification 3 - id: verification_continue_3 - if: ${{ always() && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_2.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_3.outcome }} - - name: Prepare repository verification 4 - id: verification_setup_4 - if: ${{ !cancelled() && steps.verification_continue_3.outcome == 'success' && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_3.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_3.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_3.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_3.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_3.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_3.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_3.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_3.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_3.outputs.verification-tmpdir }} - - name: Continue repository verification 4 - id: verification_continue_4 - if: ${{ always() && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_3.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_4.outcome }} - - name: Prepare repository verification 5 - id: verification_setup_5 - if: ${{ !cancelled() && steps.verification_continue_4.outcome == 'success' && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_4.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_4.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_4.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_4.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_4.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_4.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_4.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_4.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_4.outputs.verification-tmpdir }} - - name: Continue repository verification 5 - id: verification_continue_5 - if: ${{ always() && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_4.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_5.outcome }} - - name: Prepare repository verification 6 - id: verification_setup_6 - if: ${{ !cancelled() && steps.verification_continue_5.outcome == 'success' && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_5.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_5.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_5.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_5.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_5.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_5.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_5.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_5.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_5.outputs.verification-tmpdir }} - - name: Continue repository verification 6 - id: verification_continue_6 - if: ${{ always() && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_5.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_6.outcome }} - - name: Prepare repository verification 7 - id: verification_setup_7 - if: ${{ !cancelled() && steps.verification_continue_6.outcome == 'success' && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_6.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_6.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_6.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_6.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_6.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_6.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_6.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_6.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_6.outputs.verification-tmpdir }} - - name: Continue repository verification 7 - id: verification_continue_7 - if: ${{ always() && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_6.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_7.outcome }} - - name: Prepare repository verification 8 - id: verification_setup_8 - if: ${{ !cancelled() && steps.verification_continue_7.outcome == 'success' && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_7.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_7.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_7.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_7.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_7.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_7.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_7.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_7.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_7.outputs.verification-tmpdir }} - - name: Continue repository verification 8 - id: verification_continue_8 - if: ${{ always() && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_7.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_8.outcome }} - - name: Prepare repository verification 9 - id: verification_setup_9 - if: ${{ !cancelled() && steps.verification_continue_8.outcome == 'success' && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_8.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_8.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_8.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_8.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_8.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_8.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_8.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_8.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_8.outputs.verification-tmpdir }} - - name: Continue repository verification 9 - id: verification_continue_9 - if: ${{ always() && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_8.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_9.outcome }} - - name: Prepare repository verification 10 - id: verification_setup_10 - if: ${{ !cancelled() && steps.verification_continue_9.outcome == 'success' && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_9.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_9.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_9.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_9.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_9.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_9.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_9.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_9.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_9.outputs.verification-tmpdir }} - - name: Continue repository verification 10 - id: verification_continue_10 - if: ${{ always() && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_9.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_10.outcome }} - - name: Prepare repository verification 11 - id: verification_setup_11 - if: ${{ !cancelled() && steps.verification_continue_10.outcome == 'success' && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_10.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_10.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_10.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_10.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_10.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_10.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_10.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_10.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_10.outputs.verification-tmpdir }} - - name: Continue repository verification 11 - id: verification_continue_11 - if: ${{ always() && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_10.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_11.outcome }} - - name: Prepare repository verification 12 - id: verification_setup_12 - if: ${{ !cancelled() && steps.verification_continue_11.outcome == 'success' && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_11.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_11.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_11.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_11.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_11.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_11.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_11.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_11.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_11.outputs.verification-tmpdir }} - - name: Continue repository verification 12 - id: verification_continue_12 - if: ${{ always() && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_11.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_12.outcome }} - - name: Prepare repository verification 13 - id: verification_setup_13 - if: ${{ !cancelled() && steps.verification_continue_12.outcome == 'success' && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_12.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_12.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_12.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_12.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_12.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_12.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_12.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_12.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_12.outputs.verification-tmpdir }} - - name: Continue repository verification 13 - id: verification_continue_13 - if: ${{ always() && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_12.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_13.outcome }} - - name: Prepare repository verification 14 - id: verification_setup_14 - if: ${{ !cancelled() && steps.verification_continue_13.outcome == 'success' && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_13.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_13.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_13.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_13.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_13.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_13.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_13.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_13.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_13.outputs.verification-tmpdir }} - - name: Continue repository verification 14 - id: verification_continue_14 - if: ${{ always() && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_13.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_14.outcome }} - - name: Prepare repository verification 15 - id: verification_setup_15 - if: ${{ !cancelled() && steps.verification_continue_14.outcome == 'success' && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_14.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_14.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_14.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_14.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_14.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_14.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_14.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_14.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_14.outputs.verification-tmpdir }} - - name: Continue repository verification 15 - id: verification_continue_15 - if: ${{ always() && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_14.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_15.outcome }} - - name: Prepare repository verification 16 - id: verification_setup_16 - if: ${{ !cancelled() && steps.verification_continue_15.outcome == 'success' && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_15.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_15.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_15.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_15.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_15.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_15.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_15.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_15.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_15.outputs.verification-tmpdir }} - - name: Continue repository verification 16 - id: verification_continue_16 - if: ${{ always() && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_15.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_16.outcome }} - - name: Prepare repository verification 17 - id: verification_setup_17 - if: ${{ !cancelled() && steps.verification_continue_16.outcome == 'success' && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_16.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_16.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_16.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_16.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_16.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_16.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_16.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_16.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_16.outputs.verification-tmpdir }} - - name: Continue repository verification 17 - id: verification_continue_17 - if: ${{ always() && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_16.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_17.outcome }} - - name: Prepare repository verification 18 - id: verification_setup_18 - if: ${{ !cancelled() && steps.verification_continue_17.outcome == 'success' && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_17.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_17.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_17.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_17.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_17.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_17.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_17.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_17.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_17.outputs.verification-tmpdir }} - - name: Continue repository verification 18 - id: verification_continue_18 - if: ${{ always() && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_17.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_18.outcome }} - - name: Prepare repository verification 19 - id: verification_setup_19 - if: ${{ !cancelled() && steps.verification_continue_18.outcome == 'success' && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_18.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_18.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_18.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_18.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_18.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_18.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_18.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_18.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_18.outputs.verification-tmpdir }} - - name: Continue repository verification 19 - id: verification_continue_19 - if: ${{ always() && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_18.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_19.outcome }} - - name: Prepare repository verification 20 - id: verification_setup_20 - if: ${{ !cancelled() && steps.verification_continue_19.outcome == 'success' && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_19.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_19.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_19.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_19.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_19.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_19.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_19.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_19.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_19.outputs.verification-tmpdir }} - - name: Continue repository verification 20 - id: verification_continue_20 - if: ${{ always() && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_19.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_20.outcome }} - - name: Complete repository verification - id: verification_complete - if: ${{ always() && steps.copilot.outputs.verification-ticket != '' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: finish - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - # copilot:native-verification:end + with: + runs-on: '["self-hosted","codex","Linux"]' + issue-managed-branches: 'true' + pre-branch-sdd: 'true' + ai-ignore-files: build/*,specs/CATALOG.md + prepare-source-verification: true + secrets: + PAT: ${{ secrets.PAT }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} diff --git a/.github/workflows/copilot_pull_request_comment.yml b/.github/workflows/copilot_pull_request_comment.yml index b3e5f1f38..77b1e3694 100644 --- a/.github/workflows/copilot_pull_request_comment.yml +++ b/.github/workflows/copilot_pull_request_comment.yml @@ -1,694 +1,32 @@ +# Generated by scripts/generate-native-verification-workflows.cjs +# Project runtimes: .copilot/verification-prerequisites.json +# Dependencies: .github/actions/copilot-verification-setup/action.yml +# https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites name: Copilot - Pull Request Comment - -on: +'on': pull_request_review_comment: - types: [created, edited] - + types: + - created + - edited jobs: copilot-pull-requests: if: ${{ (vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN) && github.event.pull_request.head.repo.full_name == github.repository }} - name: Copilot - Pull Request Comment - runs-on: [self-hosted, codex, Linux] - timeout-minutes: 120 + uses: $/.github/workflows/copilot_comment_runtime.yml permissions: checks: write contents: read - env: - # Preparation covers parser whitespace and mentions; authorization stays in the Action. - COPILOT_PREPARE_VERIFICATION: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS != '' && ((contains(github.event.comment.body, '/copilot') && ((contains(github.event.comment.body, 'sync-branch') && !contains(github.event.comment.body, '--dry-run')) || contains(github.event.comment.body, 'implement') || contains(github.event.comment.body, 'fix') || contains(github.event.comment.body, 'remember'))) || (vars.COPILOT_BOT_LOGIN != '' && contains(github.event.comment.body, format('@{0}', vars.COPILOT_BOT_LOGIN)) && !contains(github.event.comment.body, '--dry-run'))) }} - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Prepare repository pnpm - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - uses: pnpm/action-setup@v5 - with: - version: 10.12.4 - standalone: false - dest: ${{ runner.temp }}/setup-pnpm-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }} - - - name: Prepare repository Node - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - uses: actions/setup-node@v7 - with: - node-version: '24.x' - - - name: Install repository verification dependencies - if: env.COPILOT_PREPARE_VERIFICATION == 'true' - shell: bash - run: pnpm install --frozen-lockfile --ignore-scripts - - - name: Snapshot the Copilot runtime before candidate changes - id: prepare_native_runtime - run: node scripts/prepare-native-source-action.cjs - shell: bash - - - uses: ./../.copilot-native-runtime - id: copilot - with: &copilot-inputs - repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }} - issues-locale: ${{ vars.ISSUES_LOCALE || '' }} - pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }} - issue-workflow-profile: ${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }} - issue-managed-branches: true - pre-branch-sdd: true - verification-setup: ${{ vars.VERIFICATION_SETUP || 'false' }} - ai-ignore-files: build/*,specs/CATALOG.md - debug: ${{ vars.DEBUG }} - agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }} - agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }} - agent-effort: ${{ vars.AGENT_EFFORT }} - agent-executable: ${{ vars.AGENT_EXECUTABLE }} - findings-provider: ${{ vars.FINDINGS_PROVIDER }} - findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }} - findings-model: ${{ vars.FINDINGS_MODEL }} - findings-effort: ${{ vars.FINDINGS_EFFORT }} - findings-executable: ${{ vars.FINDINGS_EXECUTABLE }} - fixer-provider: ${{ vars.FIXER_PROVIDER }} - fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }} - fixer-model: ${{ vars.FIXER_MODEL }} - fixer-effort: ${{ vars.FIXER_EFFORT }} - fixer-executable: ${{ vars.FIXER_EXECUTABLE }} - reviewer-provider: ${{ vars.REVIEWER_PROVIDER }} - reviewer-model-provider: ${{ vars.REVIEWER_MODEL_PROVIDER }} - reviewer-model: ${{ vars.REVIEWER_MODEL }} - reviewer-effort: ${{ vars.REVIEWER_EFFORT }} - reviewer-executable: ${{ vars.REVIEWER_EXECUTABLE }} - planner-provider: ${{ vars.PLANNER_PROVIDER }} - planner-model-provider: ${{ vars.PLANNER_MODEL_PROVIDER }} - planner-model: ${{ vars.PLANNER_MODEL }} - planner-effort: ${{ vars.PLANNER_EFFORT }} - planner-executable: ${{ vars.PLANNER_EXECUTABLE }} - tester-provider: ${{ vars.TESTER_PROVIDER }} - tester-model-provider: ${{ vars.TESTER_MODEL_PROVIDER }} - tester-model: ${{ vars.TESTER_MODEL }} - tester-effort: ${{ vars.TESTER_EFFORT }} - tester-executable: ${{ vars.TESTER_EXECUTABLE }} - project-ids: ${{ vars.PROJECT_IDS }} - token: ${{ secrets.PAT }} - bugbot-fix-verify-commands: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }} - bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }} - bugbot-effort: ${{ vars.BUGBOT_EFFORT || 'smart' }} - bugbot-review-drafts: ${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }} - bugbot-trace-rules: ${{ vars.BUGBOT_TRACE_RULES || 'false' }} - bugbot-suggested-changes: ${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }} - bugbot-telemetry: ${{ vars.BUGBOT_TELEMETRY || 'true' }} - bugbot-fail-on-unresolved: ${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }} - bugbot-organization-rules: ${{ vars.BUGBOT_ORGANIZATION_RULES }} - env: - COPILOT_NATIVE_PHASE: prepare - COPILOT_NATIVE_RUNTIME_CACHE: ${{ steps.prepare_native_runtime.outputs.path }} - AGENT_PROVIDER: ${{ vars.AGENT_PROVIDER || 'codex' }} - AGENT_MODEL_PROVIDER: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - AGENT_MODEL: ${{ vars.AGENT_MODEL }} - AGENT_EFFORT: ${{ vars.AGENT_EFFORT }} - AGENT_ALLOWED_MODEL_PROVIDERS: ${{ vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai' }} - AGENT_ALLOWED_MODELS: ${{ vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna' }} - AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} - CURSOR_API_KEY: ${{ (vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || '' }} - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - COPILOT_EVIDENCE_TOKEN: ${{ github.token }} - - # copilot:native-verification:start - - name: Prepare repository verification 1 - id: verification_setup_1 - if: ${{ !cancelled() && steps.copilot.outcome == 'success' && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.copilot.outputs.verification-home }} - USERPROFILE: ${{ steps.copilot.outputs.verification-userprofile }} - APPDATA: ${{ steps.copilot.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.copilot.outputs.verification-localappdata }} - PATH: ${{ steps.copilot.outputs.verification-path }} - JAVA_HOME: ${{ steps.copilot.outputs.verification-java_home }} - TMP: ${{ steps.copilot.outputs.verification-tmp }} - TEMP: ${{ steps.copilot.outputs.verification-temp }} - TMPDIR: ${{ steps.copilot.outputs.verification-tmpdir }} - - name: Continue repository verification 1 - id: verification_continue_1 - if: ${{ always() && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.copilot.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_1.outcome }} - - name: Prepare repository verification 2 - id: verification_setup_2 - if: ${{ !cancelled() && steps.verification_continue_1.outcome == 'success' && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_1.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_1.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_1.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_1.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_1.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_1.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_1.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_1.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_1.outputs.verification-tmpdir }} - - name: Continue repository verification 2 - id: verification_continue_2 - if: ${{ always() && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_1.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_2.outcome }} - - name: Prepare repository verification 3 - id: verification_setup_3 - if: ${{ !cancelled() && steps.verification_continue_2.outcome == 'success' && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_2.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_2.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_2.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_2.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_2.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_2.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_2.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_2.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_2.outputs.verification-tmpdir }} - - name: Continue repository verification 3 - id: verification_continue_3 - if: ${{ always() && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_2.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_3.outcome }} - - name: Prepare repository verification 4 - id: verification_setup_4 - if: ${{ !cancelled() && steps.verification_continue_3.outcome == 'success' && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_3.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_3.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_3.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_3.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_3.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_3.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_3.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_3.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_3.outputs.verification-tmpdir }} - - name: Continue repository verification 4 - id: verification_continue_4 - if: ${{ always() && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_3.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_4.outcome }} - - name: Prepare repository verification 5 - id: verification_setup_5 - if: ${{ !cancelled() && steps.verification_continue_4.outcome == 'success' && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_4.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_4.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_4.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_4.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_4.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_4.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_4.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_4.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_4.outputs.verification-tmpdir }} - - name: Continue repository verification 5 - id: verification_continue_5 - if: ${{ always() && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_4.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_5.outcome }} - - name: Prepare repository verification 6 - id: verification_setup_6 - if: ${{ !cancelled() && steps.verification_continue_5.outcome == 'success' && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_5.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_5.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_5.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_5.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_5.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_5.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_5.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_5.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_5.outputs.verification-tmpdir }} - - name: Continue repository verification 6 - id: verification_continue_6 - if: ${{ always() && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_5.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_6.outcome }} - - name: Prepare repository verification 7 - id: verification_setup_7 - if: ${{ !cancelled() && steps.verification_continue_6.outcome == 'success' && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_6.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_6.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_6.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_6.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_6.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_6.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_6.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_6.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_6.outputs.verification-tmpdir }} - - name: Continue repository verification 7 - id: verification_continue_7 - if: ${{ always() && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_6.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_7.outcome }} - - name: Prepare repository verification 8 - id: verification_setup_8 - if: ${{ !cancelled() && steps.verification_continue_7.outcome == 'success' && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_7.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_7.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_7.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_7.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_7.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_7.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_7.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_7.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_7.outputs.verification-tmpdir }} - - name: Continue repository verification 8 - id: verification_continue_8 - if: ${{ always() && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_7.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_8.outcome }} - - name: Prepare repository verification 9 - id: verification_setup_9 - if: ${{ !cancelled() && steps.verification_continue_8.outcome == 'success' && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_8.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_8.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_8.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_8.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_8.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_8.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_8.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_8.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_8.outputs.verification-tmpdir }} - - name: Continue repository verification 9 - id: verification_continue_9 - if: ${{ always() && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_8.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_9.outcome }} - - name: Prepare repository verification 10 - id: verification_setup_10 - if: ${{ !cancelled() && steps.verification_continue_9.outcome == 'success' && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_9.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_9.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_9.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_9.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_9.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_9.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_9.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_9.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_9.outputs.verification-tmpdir }} - - name: Continue repository verification 10 - id: verification_continue_10 - if: ${{ always() && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_9.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_10.outcome }} - - name: Prepare repository verification 11 - id: verification_setup_11 - if: ${{ !cancelled() && steps.verification_continue_10.outcome == 'success' && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_10.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_10.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_10.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_10.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_10.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_10.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_10.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_10.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_10.outputs.verification-tmpdir }} - - name: Continue repository verification 11 - id: verification_continue_11 - if: ${{ always() && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_10.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_11.outcome }} - - name: Prepare repository verification 12 - id: verification_setup_12 - if: ${{ !cancelled() && steps.verification_continue_11.outcome == 'success' && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_11.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_11.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_11.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_11.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_11.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_11.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_11.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_11.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_11.outputs.verification-tmpdir }} - - name: Continue repository verification 12 - id: verification_continue_12 - if: ${{ always() && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_11.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_12.outcome }} - - name: Prepare repository verification 13 - id: verification_setup_13 - if: ${{ !cancelled() && steps.verification_continue_12.outcome == 'success' && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_12.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_12.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_12.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_12.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_12.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_12.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_12.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_12.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_12.outputs.verification-tmpdir }} - - name: Continue repository verification 13 - id: verification_continue_13 - if: ${{ always() && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_12.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_13.outcome }} - - name: Prepare repository verification 14 - id: verification_setup_14 - if: ${{ !cancelled() && steps.verification_continue_13.outcome == 'success' && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_13.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_13.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_13.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_13.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_13.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_13.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_13.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_13.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_13.outputs.verification-tmpdir }} - - name: Continue repository verification 14 - id: verification_continue_14 - if: ${{ always() && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_13.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_14.outcome }} - - name: Prepare repository verification 15 - id: verification_setup_15 - if: ${{ !cancelled() && steps.verification_continue_14.outcome == 'success' && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_14.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_14.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_14.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_14.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_14.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_14.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_14.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_14.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_14.outputs.verification-tmpdir }} - - name: Continue repository verification 15 - id: verification_continue_15 - if: ${{ always() && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_14.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_15.outcome }} - - name: Prepare repository verification 16 - id: verification_setup_16 - if: ${{ !cancelled() && steps.verification_continue_15.outcome == 'success' && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_15.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_15.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_15.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_15.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_15.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_15.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_15.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_15.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_15.outputs.verification-tmpdir }} - - name: Continue repository verification 16 - id: verification_continue_16 - if: ${{ always() && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_15.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_16.outcome }} - - name: Prepare repository verification 17 - id: verification_setup_17 - if: ${{ !cancelled() && steps.verification_continue_16.outcome == 'success' && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_16.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_16.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_16.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_16.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_16.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_16.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_16.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_16.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_16.outputs.verification-tmpdir }} - - name: Continue repository verification 17 - id: verification_continue_17 - if: ${{ always() && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_16.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_17.outcome }} - - name: Prepare repository verification 18 - id: verification_setup_18 - if: ${{ !cancelled() && steps.verification_continue_17.outcome == 'success' && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_17.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_17.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_17.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_17.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_17.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_17.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_17.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_17.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_17.outputs.verification-tmpdir }} - - name: Continue repository verification 18 - id: verification_continue_18 - if: ${{ always() && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_17.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_18.outcome }} - - name: Prepare repository verification 19 - id: verification_setup_19 - if: ${{ !cancelled() && steps.verification_continue_18.outcome == 'success' && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_18.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_18.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_18.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_18.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_18.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_18.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_18.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_18.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_18.outputs.verification-tmpdir }} - - name: Continue repository verification 19 - id: verification_continue_19 - if: ${{ always() && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_18.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_19.outcome }} - - name: Prepare repository verification 20 - id: verification_setup_20 - if: ${{ !cancelled() && steps.verification_continue_19.outcome == 'success' && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_19.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_19.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_19.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_19.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_19.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_19.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_19.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_19.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_19.outputs.verification-tmpdir }} - - name: Continue repository verification 20 - id: verification_continue_20 - if: ${{ always() && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_19.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_20.outcome }} - - name: Complete repository verification - id: verification_complete - if: ${{ always() && steps.copilot.outputs.verification-ticket != '' }} - uses: ./../.copilot-native-runtime - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: finish - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - # copilot:native-verification:end + with: + runs-on: '["self-hosted","codex","Linux"]' + issue-managed-branches: 'true' + pre-branch-sdd: 'true' + ai-ignore-files: build/*,specs/CATALOG.md + prepare-source-verification: true + secrets: + PAT: ${{ secrets.PAT }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} diff --git a/build/cli/index.js b/build/cli/index.js index 81eaa6c34..770378924 100755 --- a/build/cli/index.js +++ b/build/cli/index.js @@ -90561,6 +90561,63 @@ function isCopilotCommentRequest(commentBody, botLogin) { } +/***/ }), + +/***/ 33430: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.COPILOT_COMMENT_REMOTE_WORKFLOW = exports.COPILOT_COMMENT_SELF_WORKFLOW = exports.COPILOT_COMMENT_RUNTIME = void 0; +exports.isCopilotCommentWorkflow = isCopilotCommentWorkflow; +exports.isCopilotCommentRunner = isCopilotCommentRunner; +exports.copilotCommentRunner = copilotCommentRunner; +/** The comment coordinator is a versioned Copilot workflow, not an arbitrary reusable job. */ +exports.COPILOT_COMMENT_RUNTIME = 'copilot_comment_runtime.yml'; +exports.COPILOT_COMMENT_SELF_WORKFLOW = `$/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}`; +exports.COPILOT_COMMENT_REMOTE_WORKFLOW = `vypdev/copilot/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}@v3`; +function isCopilotCommentWorkflow(value) { + return typeof value === 'string' && (value === exports.COPILOT_COMMENT_SELF_WORKFLOW + || /^vypdev\/copilot\/\.github\/workflows\/copilot_comment_runtime\.yml@(?:v3(?:\.[0-9]+\.[0-9]+)?|[a-f0-9]{40})$/u.test(value)); +} +const literal = (value) => typeof value === 'string' && value.length > 0 && value.length <= 100 + && value === value.trim() && !/[\p{Cc}\p{Cf}${}<>]/u.test(value); +const labels = (value) => literal(value) || Array.isArray(value) && value.length > 0 && value.length <= 10 + && value.every(literal) && new Set(value.map(label => label.toLowerCase())).size === value.length; +/** Runner routing is literal data; expressions need their original full workflow reviewed. */ +function isCopilotCommentRunner(value) { + if (labels(value)) + return true; + if (!value || typeof value !== 'object' || Array.isArray(value)) + return false; + const route = value; + const keys = Object.keys(route); + return keys.length > 0 && (route.group !== undefined || route.labels !== undefined) + && keys.every(key => key === 'group' || key === 'labels') + && (route.group === undefined || literal(route.group)) + && (route.labels === undefined || labels(route.labels)); +} +function copilotCommentRunner(job) { + if (!job || !isCopilotCommentWorkflow(job.uses)) + return job?.['runs-on']; + const inputs = job.with; + if (typeof inputs?.['runs-on'] !== 'string') + throw new Error('Comment workflow runner JSON is unavailable; review the workflow separately.'); + try { + if (inputs['runs-on'].length > 16000) + throw new Error('Runner JSON exceeds its bound.'); + const route = JSON.parse(inputs['runs-on']); + if (!isCopilotCommentRunner(route)) + throw new Error('Unsupported execution route.'); + return route; + } + catch { + throw new Error('Comment workflow runner JSON is invalid; review the workflow separately.'); + } +} + + /***/ }), /***/ 72418: @@ -100421,10 +100478,13 @@ exports.SetupGithubIdentityQueryAdapter = SetupGithubIdentityQueryAdapter; /***/ }), /***/ 75545: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.SetupManagementWorkspaceAdapter = void 0; const node_fs_1 = __nccwpck_require__(87561); @@ -100432,6 +100492,8 @@ const node_path_1 = __nccwpck_require__(49411); const node_crypto_1 = __nccwpck_require__(6005); const js_yaml_1 = __nccwpck_require__(783); const sensitive_text_1 = __nccwpck_require__(47122); +const copilot_comment_workflow_1 = __nccwpck_require__(33430); +const copilot_comment_inputs_json_1 = __importDefault(__nccwpck_require__(78593)); const object = (value) => value && typeof value === 'object' && !Array.isArray(value) ? value : {}; const digest = (source) => (0, node_crypto_1.createHash)('sha256').update(source).digest('hex'); function readDocument(path) { @@ -100522,13 +100584,34 @@ class SetupManagementWorkspaceAdapter { inspectWorkflow(file, localAction) { const { source, document } = readDocument((0, node_path_1.join)(this.root, '.github', 'workflows', file)); const steps = workflowSteps(document); - const knownLocalAction = steps.some(({ step }) => step.uses === './') ? Boolean(localAction()) : false; - return steps.flatMap(({ job, step }) => { - if (!this.isCopilotStep(step, knownLocalAction)) - return []; - const inputs = Object.entries(object(step.with)).flatMap(([name, value]) => installedInput(name, value)); - return [{ file, action: step.uses, digest: digest(source), environmentScoped: environmentScoped(document, job, step), inputs }]; + const jobs = Object.values(object(document.jobs)).map(object); + if (jobs.some(job => typeof job.uses === 'string' + && /^(?:vypdev\/copilot\/|[.$]\/)\.github\/workflows\/copilot_comment_runtime\.yml(?:@|$)/iu.test(job.uses) + && !(0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(job.uses))) + throw new Error('Unsupported comment workflow reference.'); + const calls = jobs.filter(job => (0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(job.uses)); + if (calls.some(job => job.uses === copilot_comment_workflow_1.COPILOT_COMMENT_SELF_WORKFLOW) && !localAction()) + throw new Error('Unverified source comment workflow.'); + const reusable = calls.map(job => { + const overrides = object(job.with); + if (Object.keys(overrides).some(key => !['runs-on', 'issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files', 'prepare-source-verification'].includes(key))) + throw new Error('Unknown comment workflow input.'); + const bindings = { ...copilot_comment_inputs_json_1.default }; + for (const name of ['issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files']) { + if (overrides[name] !== undefined && overrides[name] !== '') + bindings[name] = overrides[name]; + } + return { file, action: job.uses === copilot_comment_workflow_1.COPILOT_COMMENT_SELF_WORKFLOW ? './' : `vypdev/copilot@${String(job.uses).split('@').at(-1)}`, + digest: digest(source), environmentScoped: environmentScoped(document, job, {}), + inputs: Object.entries(bindings).flatMap(([name, value]) => installedInput(name, value)) }; }); + const knownLocalAction = steps.some(({ step }) => step.uses === './') ? Boolean(localAction()) : false; + return [...reusable, ...steps.flatMap(({ job, step }) => { + if (!this.isCopilotStep(step, knownLocalAction)) + return []; + const inputs = Object.entries(object(step.with)).flatMap(([name, value]) => installedInput(name, value)); + return [{ file, action: step.uses, digest: digest(source), environmentScoped: environmentScoped(document, job, step), inputs }]; + })]; } isCopilotStep(step, knownLocalAction) { if (typeof step.uses !== 'string') @@ -106805,6 +106888,7 @@ const sensitive_text_1 = __nccwpck_require__(47122); const repository_agent_guidance_policy_1 = __nccwpck_require__(67402); const setup_verification_action_1 = __nccwpck_require__(33156); const setup_verification_action_2 = __nccwpck_require__(12471); +const copilot_comment_workflow_1 = __nccwpck_require__(33430); exports.SETUP_RUNNER_SNAPSHOT = '.copilot/runner-profile.json'; const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined; @@ -106870,7 +106954,7 @@ function inspectSetupInstallation(root, configuration, setup = (0, node_path_1.j if (!parsedJobs) throw new Error('Workflow jobs are unavailable for review.'); for (const [job, raw] of Object.entries(parsedJobs)) { - const runsOn = object(raw)?.['runs-on']; + const runsOn = (0, copilot_comment_workflow_1.copilotCommentRunner)(object(raw)); if (runsOn === undefined) continue; // reusable workflow calls have no runner jobs.push({ file, job, role: (0, setup_runner_policy_1.setupRunnerRole)(file, job) ?? 'validation', @@ -106977,6 +107061,7 @@ const js_yaml_1 = __nccwpck_require__(783); const node_util_1 = __nccwpck_require__(47261); const setup_runner_policy_1 = __nccwpck_require__(91027); const action_types_1 = __nccwpck_require__(19625); +const copilot_comment_workflow_1 = __nccwpck_require__(33430); const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined; const document = (value) => { try { @@ -106998,6 +107083,8 @@ const runner = (value) => labels(value) || !!object(value) && (object(value).labels === undefined || labels(object(value).labels)); const copilotCommands = new Set(Object.values(action_types_1.ACTIONS)); const callsRootAction = (jobs) => !!jobs && Object.values(jobs).some(job => { + if (object(job)?.uses === copilot_comment_workflow_1.COPILOT_COMMENT_SELF_WORKFLOW) + return true; const steps = object(job)?.steps; return Array.isArray(steps) && steps.some(step => { const invocation = object(step); @@ -107060,6 +107147,32 @@ function renderSetupWorkflowUpgrade(template, existing, selection) { const templateJobs = object(document(template)?.jobs); if (!previousJobs || !templateJobs) throw new Error('Workflow jobs cannot be inspected; review the workflow separately.'); + if (Object.values(templateJobs).some(job => (0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(object(job)?.uses))) { + const parsed = document(template); + const jobs = object(parsed.jobs); + let changed = false; + for (const [name, value] of Object.entries(jobs)) { + const job = object(value); + if (!(0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(job.uses)) + throw new Error('Mixed comment workflow jobs require separate workflow review before setup.'); + const previousJob = object(previousJobs[name]); + if (Array.isArray(previousJob?.steps) && previousJob.steps.some(raw => { + const uses = object(raw)?.uses; + return typeof uses !== 'string' || !(uses.startsWith('actions/checkout@') + || /^vypdev\/copilot@[^\s]+$/u.test(uses) || uses === './.git/copilot-verification-setup'); + })) + throw new Error('Custom comment job steps require migration to the reviewed repository verification setup action before switching to the reusable workflow. Review the workflow separately.'); + const retained = (0, setup_runner_policy_1.selectedSetupRunsOn)(selection?.runners, selection && (0, setup_runner_policy_1.setupRunnerRole)(selection.file, name)) + ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(previousJob) ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(job); + if (!runner(retained)) + throw new Error('Existing runner selection is invalid; review the workflow separately.'); + if (JSON.stringify(retained).includes('${{') && existing !== template) + throw new Error('Dynamic runner selection requires separate workflow review before setup.'); + changed || (changed = !(0, node_util_1.isDeepStrictEqual)(retained, (0, copilot_comment_workflow_1.copilotCommentRunner)(job))); + job.with = { ...object(job.with), 'runs-on': JSON.stringify(retained) }; + } + return changed ? (0, js_yaml_1.dump)(parsed, { noRefs: true, lineWidth: -1 }) : template; + } const lines = template.split('\n'); let job = ''; let insideJobs = false; @@ -118890,6 +119003,14 @@ module.exports = JSON.parse('{"single":{"topLeft":"┌","top":"─","topRight":" "use strict"; module.exports = JSON.parse('{"revision":"2026-10-02.standalone.1","providers":{"codex":{"executable":"codex","reviewedVersion":"codex-cli 0.156.1","legacyNpmPackage":"@openai/codex","installation":{"unixScript":"https://chatgpt.com/codex/install.sh","windowsScript":"https://chatgpt.com/codex/install.ps1"}},"opencode":{"executable":"opencode","reviewedVersion":"1.18.3","legacyNpmPackage":"opencode-ai","installation":{"unixScript":"https://opencode.ai/install","windowsReleaseApi":"https://api.github.com/repos/anomalyco/opencode/releases/latest"}},"cursor":{"executable":"agent","reviewedVersion":"2026.09.10-fd3934a","installation":{"unixScript":"https://cursor.com/install","windowsScript":"https://cursor.com/install?win32=true"}}}}'); +/***/ }), + +/***/ 78593: +/***/ ((module) => { + +"use strict"; +module.exports = JSON.parse('{"repository-locale":"${{ vars.REPOSITORY_LOCALE || \'en-US\' }}","issues-locale":"${{ vars.ISSUES_LOCALE || \'\' }}","pull-requests-locale":"${{ vars.PULL_REQUESTS_LOCALE || \'\' }}","ai-ignore-files":"${{ vars.AI_IGNORE_FILES || \'build/*\' }}","debug":"${{ vars.DEBUG }}","main-branch":"${{ vars.MAIN_BRANCH || \'master\' }}","development-branch":"${{ vars.DEVELOPMENT_BRANCH || \'develop\' }}","feature-tree":"${{ vars.FEATURE_TREE || \'feature\' }}","bugfix-tree":"${{ vars.BUGFIX_TREE || \'bugfix\' }}","hotfix-tree":"${{ vars.HOTFIX_TREE || \'hotfix\' }}","release-tree":"${{ vars.RELEASE_TREE || \'release\' }}","docs-tree":"${{ vars.DOCS_TREE || \'docs\' }}","chore-tree":"${{ vars.CHORE_TREE || \'chore\' }}","issue-managed-branches":"${{ vars.ISSUE_MANAGED_BRANCHES || \'true\' }}","pre-branch-sdd":"${{ vars.PRE_BRANCH_SDD || \'false\' }}","verification-setup":"${{ vars.VERIFICATION_SETUP || \'false\' }}","issue-workflow-profile":"${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || \'\' }}","reopen-issue-on-push":"${{ vars.REOPEN_ISSUE_ON_PUSH || \'true\' }}","desired-assignees-count":"${{ vars.DESIRED_ASSIGNEES_COUNT || \'1\' }}","desired-reviewers-count":"${{ vars.DESIRED_REVIEWERS_COUNT || \'1\' }}","commit-prefix-transforms":"${{ vars.COMMIT_PREFIX_TRANSFORMS || \'replace-slash\' }}","ai-pull-request-description-mode":"${{ vars.AI_PULL_REQUEST_DESCRIPTION_MODE || \'replace\' }}","ai-members-only":"${{ vars.AI_MEMBERS_ONLY || \'false\' }}","ai-include-reasoning":"${{ vars.AI_INCLUDE_REASONING || \'false\' }}","bugbot-severity":"${{ vars.BUGBOT_SEVERITY || \'low\' }}","bugbot-comment-limit":"${{ vars.BUGBOT_COMMENT_LIMIT || \'20\' }}","bugbot-fix-verify-commands":"${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }}","bugbot-dry-run":"${{ vars.BUGBOT_DRY_RUN || \'false\' }}","bugbot-effort":"${{ vars.BUGBOT_EFFORT || \'smart\' }}","bugbot-review-drafts":"${{ vars.BUGBOT_REVIEW_DRAFTS || \'false\' }}","bugbot-trace-rules":"${{ vars.BUGBOT_TRACE_RULES || \'false\' }}","bugbot-suggested-changes":"${{ vars.BUGBOT_SUGGESTED_CHANGES || \'true\' }}","bugbot-telemetry":"${{ vars.BUGBOT_TELEMETRY || \'true\' }}","bugbot-fail-on-unresolved":"${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || \'false\' }}","bugbot-organization-rules":"${{ vars.BUGBOT_ORGANIZATION_RULES }}","project-column-issue-created":"${{ vars.PROJECT_COLUMN_ISSUE_CREATED || \'Todo\' }}","project-column-pull-request-created":"${{ vars.PROJECT_COLUMN_PULL_REQUEST_CREATED || \'In Progress\' }}","project-column-issue-in-progress":"${{ vars.PROJECT_COLUMN_ISSUE_IN_PROGRESS || \'In Progress\' }}","project-column-pull-request-in-progress":"${{ vars.PROJECT_COLUMN_PULL_REQUEST_IN_PROGRESS || \'In Progress\' }}","agent-provider":"${{ vars.AGENT_PROVIDER || \'codex\' }}","agent-model-provider":"${{ vars.AGENT_MODEL_PROVIDER || \'openai\' }}","agent-model":"${{ vars.AGENT_MODEL || \'gpt-6-luna\' }}","agent-effort":"${{ vars.AGENT_EFFORT }}","agent-executable":"${{ vars.AGENT_EXECUTABLE }}","findings-provider":"${{ vars.FINDINGS_PROVIDER }}","findings-model-provider":"${{ vars.FINDINGS_MODEL_PROVIDER }}","findings-model":"${{ vars.FINDINGS_MODEL }}","findings-effort":"${{ vars.FINDINGS_EFFORT }}","findings-executable":"${{ vars.FINDINGS_EXECUTABLE }}","fixer-provider":"${{ vars.FIXER_PROVIDER }}","fixer-model-provider":"${{ vars.FIXER_MODEL_PROVIDER }}","fixer-model":"${{ vars.FIXER_MODEL }}","fixer-effort":"${{ vars.FIXER_EFFORT }}","fixer-executable":"${{ vars.FIXER_EXECUTABLE }}","planner-provider":"${{ vars.PLANNER_PROVIDER }}","planner-model-provider":"${{ vars.PLANNER_MODEL_PROVIDER }}","planner-model":"${{ vars.PLANNER_MODEL }}","planner-effort":"${{ vars.PLANNER_EFFORT }}","planner-executable":"${{ vars.PLANNER_EXECUTABLE }}","reviewer-provider":"${{ vars.REVIEWER_PROVIDER }}","reviewer-model-provider":"${{ vars.REVIEWER_MODEL_PROVIDER }}","reviewer-model":"${{ vars.REVIEWER_MODEL }}","reviewer-effort":"${{ vars.REVIEWER_EFFORT }}","reviewer-executable":"${{ vars.REVIEWER_EXECUTABLE }}","tester-provider":"${{ vars.TESTER_PROVIDER }}","tester-model-provider":"${{ vars.TESTER_MODEL_PROVIDER }}","tester-model":"${{ vars.TESTER_MODEL }}","tester-effort":"${{ vars.TESTER_EFFORT }}","tester-executable":"${{ vars.TESTER_EXECUTABLE }}","project-ids":"${{ vars.PROJECT_IDS }}"}'); + /***/ }) /******/ }); diff --git a/build/github_action/index.js b/build/github_action/index.js index 1addc7cdf..94e9f073a 100644 --- a/build/github_action/index.js +++ b/build/github_action/index.js @@ -81005,6 +81005,63 @@ function isCopilotCommentRequest(commentBody, botLogin) { } +/***/ }), + +/***/ 33430: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.COPILOT_COMMENT_REMOTE_WORKFLOW = exports.COPILOT_COMMENT_SELF_WORKFLOW = exports.COPILOT_COMMENT_RUNTIME = void 0; +exports.isCopilotCommentWorkflow = isCopilotCommentWorkflow; +exports.isCopilotCommentRunner = isCopilotCommentRunner; +exports.copilotCommentRunner = copilotCommentRunner; +/** The comment coordinator is a versioned Copilot workflow, not an arbitrary reusable job. */ +exports.COPILOT_COMMENT_RUNTIME = 'copilot_comment_runtime.yml'; +exports.COPILOT_COMMENT_SELF_WORKFLOW = `$/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}`; +exports.COPILOT_COMMENT_REMOTE_WORKFLOW = `vypdev/copilot/.github/workflows/${exports.COPILOT_COMMENT_RUNTIME}@v3`; +function isCopilotCommentWorkflow(value) { + return typeof value === 'string' && (value === exports.COPILOT_COMMENT_SELF_WORKFLOW + || /^vypdev\/copilot\/\.github\/workflows\/copilot_comment_runtime\.yml@(?:v3(?:\.[0-9]+\.[0-9]+)?|[a-f0-9]{40})$/u.test(value)); +} +const literal = (value) => typeof value === 'string' && value.length > 0 && value.length <= 100 + && value === value.trim() && !/[\p{Cc}\p{Cf}${}<>]/u.test(value); +const labels = (value) => literal(value) || Array.isArray(value) && value.length > 0 && value.length <= 10 + && value.every(literal) && new Set(value.map(label => label.toLowerCase())).size === value.length; +/** Runner routing is literal data; expressions need their original full workflow reviewed. */ +function isCopilotCommentRunner(value) { + if (labels(value)) + return true; + if (!value || typeof value !== 'object' || Array.isArray(value)) + return false; + const route = value; + const keys = Object.keys(route); + return keys.length > 0 && (route.group !== undefined || route.labels !== undefined) + && keys.every(key => key === 'group' || key === 'labels') + && (route.group === undefined || literal(route.group)) + && (route.labels === undefined || labels(route.labels)); +} +function copilotCommentRunner(job) { + if (!job || !isCopilotCommentWorkflow(job.uses)) + return job?.['runs-on']; + const inputs = job.with; + if (typeof inputs?.['runs-on'] !== 'string') + throw new Error('Comment workflow runner JSON is unavailable; review the workflow separately.'); + try { + if (inputs['runs-on'].length > 16000) + throw new Error('Runner JSON exceeds its bound.'); + const route = JSON.parse(inputs['runs-on']); + if (!isCopilotCommentRunner(route)) + throw new Error('Unsupported execution route.'); + return route; + } + catch { + throw new Error('Comment workflow runner JSON is invalid; review the workflow separately.'); + } +} + + /***/ }), /***/ 72418: @@ -92895,6 +92952,7 @@ const sensitive_text_1 = __nccwpck_require__(47122); const repository_agent_guidance_policy_1 = __nccwpck_require__(67402); const setup_verification_action_1 = __nccwpck_require__(33156); const setup_verification_action_2 = __nccwpck_require__(12471); +const copilot_comment_workflow_1 = __nccwpck_require__(33430); exports.SETUP_RUNNER_SNAPSHOT = '.copilot/runner-profile.json'; const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined; @@ -92960,7 +93018,7 @@ function inspectSetupInstallation(root, configuration, setup = (0, node_path_1.j if (!parsedJobs) throw new Error('Workflow jobs are unavailable for review.'); for (const [job, raw] of Object.entries(parsedJobs)) { - const runsOn = object(raw)?.['runs-on']; + const runsOn = (0, copilot_comment_workflow_1.copilotCommentRunner)(object(raw)); if (runsOn === undefined) continue; // reusable workflow calls have no runner jobs.push({ file, job, role: (0, setup_runner_policy_1.setupRunnerRole)(file, job) ?? 'validation', @@ -93067,6 +93125,7 @@ const js_yaml_1 = __nccwpck_require__(783); const node_util_1 = __nccwpck_require__(47261); const setup_runner_policy_1 = __nccwpck_require__(91027); const action_types_1 = __nccwpck_require__(19625); +const copilot_comment_workflow_1 = __nccwpck_require__(33430); const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined; const document = (value) => { try { @@ -93088,6 +93147,8 @@ const runner = (value) => labels(value) || !!object(value) && (object(value).labels === undefined || labels(object(value).labels)); const copilotCommands = new Set(Object.values(action_types_1.ACTIONS)); const callsRootAction = (jobs) => !!jobs && Object.values(jobs).some(job => { + if (object(job)?.uses === copilot_comment_workflow_1.COPILOT_COMMENT_SELF_WORKFLOW) + return true; const steps = object(job)?.steps; return Array.isArray(steps) && steps.some(step => { const invocation = object(step); @@ -93150,6 +93211,32 @@ function renderSetupWorkflowUpgrade(template, existing, selection) { const templateJobs = object(document(template)?.jobs); if (!previousJobs || !templateJobs) throw new Error('Workflow jobs cannot be inspected; review the workflow separately.'); + if (Object.values(templateJobs).some(job => (0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(object(job)?.uses))) { + const parsed = document(template); + const jobs = object(parsed.jobs); + let changed = false; + for (const [name, value] of Object.entries(jobs)) { + const job = object(value); + if (!(0, copilot_comment_workflow_1.isCopilotCommentWorkflow)(job.uses)) + throw new Error('Mixed comment workflow jobs require separate workflow review before setup.'); + const previousJob = object(previousJobs[name]); + if (Array.isArray(previousJob?.steps) && previousJob.steps.some(raw => { + const uses = object(raw)?.uses; + return typeof uses !== 'string' || !(uses.startsWith('actions/checkout@') + || /^vypdev\/copilot@[^\s]+$/u.test(uses) || uses === './.git/copilot-verification-setup'); + })) + throw new Error('Custom comment job steps require migration to the reviewed repository verification setup action before switching to the reusable workflow. Review the workflow separately.'); + const retained = (0, setup_runner_policy_1.selectedSetupRunsOn)(selection?.runners, selection && (0, setup_runner_policy_1.setupRunnerRole)(selection.file, name)) + ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(previousJob) ?? (0, copilot_comment_workflow_1.copilotCommentRunner)(job); + if (!runner(retained)) + throw new Error('Existing runner selection is invalid; review the workflow separately.'); + if (JSON.stringify(retained).includes('${{') && existing !== template) + throw new Error('Dynamic runner selection requires separate workflow review before setup.'); + changed || (changed = !(0, node_util_1.isDeepStrictEqual)(retained, (0, copilot_comment_workflow_1.copilotCommentRunner)(job))); + job.with = { ...object(job.with), 'runs-on': JSON.stringify(retained) }; + } + return changed ? (0, js_yaml_1.dump)(parsed, { noRefs: true, lineWidth: -1 }) : template; + } const lines = template.split('\n'); let job = ''; let insideJobs = false; diff --git a/docs/configuration-checklist.mdx b/docs/configuration-checklist.mdx index f1f0f5d08..027b117e0 100644 --- a/docs/configuration-checklist.mdx +++ b/docs/configuration-checklist.mdx @@ -4,6 +4,10 @@ description: Required checks before enabling Copilot automation. --- # Configuration checklist +For compact comment callbacks, verify runner 2.336.0+, platform support and the +Actions policy for Copilot's reusable coordinator. Review the retained runner and +any custom bootstrap migration using the [upgrade guide](/security-operations/operations/upgrade-rollback#upgrade-an-existing-copilot-repository). + Before enabling repository verification or automated fixes, provision required project runtimes in **each** executing job and add the reviewed [runtime declaration](/security-operations/operations/verification#repository-verification-prerequisites). diff --git a/docs/configuration.mdx b/docs/configuration.mdx index 1b19107ca..57924342c 100644 --- a/docs/configuration.mdx +++ b/docs/configuration.mdx @@ -5,6 +5,13 @@ description: Detailed configuration options for Copilot # Configuration Options +The generated comment callbacks delegate their whole job to +`vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`. The coordinator +reads this repository's existing Variables and explicitly forwarded Secrets; +project setup remains isolated from provider/PAT inputs. Setup stores the reviewed +runner route as JSON in the call's `with.runs-on`, including label arrays and group +objects. See [verification and coordinator configuration](/security-operations/operations/verification#repository-owned-setup). + For a new installation, use [web setup](/setup-web). To configure a specific outcome, start with the [goal guides](/guides); they connect setup choices, runtime configuration and verification. This page is the input and scope reference. Copilot provides extensive configuration options to customize your workflow. Use the tabs below to jump to the category you need. diff --git a/docs/development/architecture.mdx b/docs/development/architecture.mdx index 4f1071274..1407ee2db 100644 --- a/docs/development/architecture.mdx +++ b/docs/development/architecture.mdx @@ -4,6 +4,16 @@ description: Clean Architecture boundaries for agent execution and workflow auto --- # Architecture +Issue/review comment callbacks are compact entrypoints into the Copilot-owned +`copilot_comment_runtime.yml` reusable workflow. One job owns the existing native +worker, project composite setup, continuations and reverse post cleanup. Internal +`uses: $/` references bind all runtime phases to the called workflow commit. The +pure known-workflow/runner contract lives in `copilot_comment_workflow.ts`; existing +setup adapters retain YAML/filesystem inspection, preview/Apply and migration. +Safe Variable/default bindings are shared by the workflow generator and maintenance +reader. See the [coordinator SDD](https://github.com/vypdev/copilot/blob/develop/specs/copilot-comment-workflow-coordinator.md) +and [operational contract](/security-operations/operations/verification#repository-owned-setup). + Verification setup onboarding uses the shared repository questionnaire and the existing `repository.verificationSetup` boolean. The package supplies a native composite starter under `setup/actions/`; the filesystem adapter inspects only diff --git a/docs/issues/comment-commands.mdx b/docs/issues/comment-commands.mdx index cc42960d2..4e1c285ef 100644 --- a/docs/issues/comment-commands.mdx +++ b/docs/issues/comment-commands.mdx @@ -5,6 +5,12 @@ description: Use @vypbot from issues and pull requests for help, analysis, plann # Comment commands +Generated comment workflows call one Copilot-owned coordinator. The command, +project dependency setup, verification and cleanup still run in the same job; +inspect the comment run's nested `Copilot` job for preparation/continuation logs. +Command permissions and result cards retain their existing behavior. See +[repository setup and verification](/security-operations/operations/verification#repository-owned-setup). + Branchless help requests stay on the read-only answer route even when natural language classification suggests a repository task. File changes require an authoritative branch from a supported surface, such as a PR review comment; diff --git a/docs/security-operations/operations/upgrade-rollback.mdx b/docs/security-operations/operations/upgrade-rollback.mdx index 81dddede7..c2076e69f 100644 --- a/docs/security-operations/operations/upgrade-rollback.mdx +++ b/docs/security-operations/operations/upgrade-rollback.mdx @@ -43,8 +43,8 @@ Copilot has three separate versioned layers: | Layer | What changes it | What still needs review | |---|---|---| | Installed CLI | `copilot upgrade` or an explicit npm/pnpm package version | The CLI prepares local files; it does not rewrite committed workflows merely by upgrading | -| Remote Action reference | The Copilot `uses` references in committed workflows | `@v3` follows the published major tag; an exact version or commit SHA stays pinned until explicitly changed | -| Generated workflow files | An approved `copilot setup --update-workflows` run | New jobs, inputs and native continuation steps must be committed, reviewed and merged | +| Remote Copilot reference | Action and reusable-workflow `uses` references in committed workflows | `@v3` follows the published major tag; an exact version or commit SHA stays pinned until explicitly changed | +| Generated workflow files | An approved `copilot setup --update-workflows` run | New jobs, inputs and coordinator calls must be committed, reviewed and merged | Moving a tag does not add steps to an old YAML file. Upgrading the CLI does not change the Action references in Git. A merge into `develop` is not a package or @@ -72,6 +72,18 @@ copilot setup --web --dry-run **3. Regenerate and review workflows.** +Before upgrading the comment callbacks, update self-hosted GitHub Actions runners +to **2.336.0+**. The centralized coordinator uses GitHub.com's self-repository +references to keep its internal Action on the exact selected workflow commit. +Verify platform support before adopting this format on other GitHub deployments. +Check that the repository/organization Actions policy permits the published +`vypdev/copilot/.github/workflows/copilot_comment_runtime.yml` reusable workflow +at your selected ref, as well as the existing Copilot Action. +If the existing comment jobs have custom dependency/bootstrap steps, migrate them +into the reviewed repository setup action before replacing those jobs; setup +blocks silently dropping them. Keep the prior reviewed callbacks until this is +ready. See [repository-owned setup](/security-operations/operations/verification#repository-owned-setup). + Apply a reviewed workflow upgrade: ```bash @@ -83,9 +95,14 @@ verification setup question disabled for this preparation pass. Review the displayed create/preserve result and changes before approval. The installer creates `.github/actions/copilot-verification-setup/action.yml` only if absent; existing action bytes and auxiliary files are preserved through upgrades. -Generated workflows use `vypdev/copilot@v3`. If your repository pins versions -or SHAs, review **every** Copilot `uses` reference, including native -continuation/post steps, and apply the same chosen compatible published ref. +Generated comment callbacks use +`vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`; other generated +callbacks continue using `vypdev/copilot@v3`. The coordinator owns setup, +continuations and cleanup in one job, keeping consumer YAML compact. If your +repository pins versions or SHAs, update the reusable-workflow and remaining +Action references to the chosen compatible published release. You do not edit +the internal `uses: $/` references: GitHub pins them to the called workflow commit. +The reviewed runner route is retained in the comment call's `with.runs-on` JSON. Workflow backups are retained under `.copilot/setup-backups/`. **4. Customize and merge on trusted main.** @@ -110,7 +127,8 @@ repository: Setup writes `VERIFICATION_SETUP` only when Variable management is enabled and follows the reviewed storage/reuse policy. With `--skip-variables`, update the effective Variable manually. Confirm that generated workflows pass the -`verification-setup` input and that the trusted action has been customized. +`VERIFICATION_SETUP` Variable through the coordinator (or the direct Action's +`verification-setup` input), and that the trusted action has been customized. Choose **Customize** when changing an existing repository Variable; **Reuse** keeps existing values. If an organization value must differ for this project, select `VERIFICATION_SETUP` in the repository Variable overrides and review the diff --git a/docs/security-operations/operations/verification.mdx b/docs/security-operations/operations/verification.mdx index 4235f05d9..43210a048 100644 --- a/docs/security-operations/operations/verification.mdx +++ b/docs/security-operations/operations/verification.mdx @@ -125,6 +125,26 @@ Each repository can prepare its dependencies in a native composite action, witho editing generated Copilot workflows. GitHub Actions executes the YAML's `uses` and `run` steps in the same job where Copilot verifies the candidate. +The generated issue-comment and PR-review-comment workflows call +`vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`. This reusable +workflow keeps the complete job inside Copilot: checkout, the admitted operation, +project setup, verification continuations and native cleanup. Consumer callbacks +contain one call; they do not copy the twenty possible continuation slots. +Your dependency action stays in your own repository. + +The coordinator reads the caller repository's existing Variables and receives +only the named Secrets forwarded by the generated callback. Provider credentials +remain scoped to the initial Copilot step. The project setup action receives the +existing private runtime environment. Setup retains the selected runner in the +call's `with.runs-on` JSON string, including self-hosted labels and runner groups. + +GitHub Actions runner **2.336.0 or newer** is required: the coordinator's `uses: $/` +references load Copilot from the exact reusable-workflow commit, including a +consumer's pinned SHA, outside the mutable project checkout. This is supported on +GitHub.com; verify equivalent platform support before adopting it elsewhere. +See [GitHub's self-repository reference announcement](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/). +The existing five-minute setup limit and 120-minute job budget remain in force. + ```mermaid flowchart LR A[Copilot prepares changes] --> B[Repository composite installs dependencies] @@ -148,8 +168,8 @@ apply the existing publication guards. A separate CI job does not prepare this j your project's reviewed runtime and dependency setup; no language, version or install command is inferred, and setup does not execute the action. 3. Update the generated comment workflows with `copilot setup --update-workflows` - and review the complete diff. They need the native setup and continuation - steps; an older callback cannot execute YAML. Review the action, auxiliary + and review the complete diff. They need the reusable coordinator call; an older + callback without native support cannot execute YAML. Review the action, auxiliary scripts and workflows onto the configured `main-branch` (`MAIN_BRANCH`, normally production). Candidate or model changes cannot replace the trusted action. 4. Enable the same question in the terminal/web assistant, or set non-secret @@ -182,6 +202,14 @@ procedure](/security-operations/operations/upgrade-rollback#upgrade-an-existing- This repository's `setup_platform_smoke.yml` is internal CI and is not installed in consumer projects. +If your old comment job contains custom bootstrap steps, keep that reviewed +workflow until you move those steps into the trusted project setup action and +review its activation. A job that calls a reusable workflow cannot also declare +its own steps. Setup blocks that migration rather than silently removing custom +preparation; it also blocks malformed runner JSON or dependent runner expressions +that require separate workflow review. Plain generated callbacks and previously +upgraded callbacks retain their static runner selection automatically. + Copilot captures the complete action directory from an immutable trusted Git SHA before candidate changes. The trusted origin ref must be available locally; generated comment workflows use a full checkout. The runner executes that snapshot diff --git a/docs/security-operations/security/self-hosted-runners.mdx b/docs/security-operations/security/self-hosted-runners.mdx index ec0aec513..a5b54e990 100644 --- a/docs/security-operations/security/self-hosted-runners.mdx +++ b/docs/security-operations/security/self-hosted-runners.mdx @@ -14,6 +14,12 @@ A self-hosted runner that can access agent credentials MUST be dedicated or isol - audit runner labels and permissions; - keep local session files outside repository workspaces. +The compact Copilot comment callbacks require GitHub Actions runner **2.336.0+** +and platform support for self-repository references. Their reusable coordinator +keeps the Action on the called workflow's exact commit. Setup retains self-hosted +labels and groups in the call's `with.runs-on` JSON; it does not change group +access or prove capacity. See [comment workflow upgrades](/security-operations/operations/upgrade-rollback#upgrade-an-existing-copilot-repository). + A shared persistent runner is not equivalent to an ephemeral trusted runner. The self-hosted platform smoke uses the local pnpm store without exporting a diff --git a/docs/setup-web.mdx b/docs/setup-web.mdx index 36e7a02c1..75db6586b 100644 --- a/docs/setup-web.mdx +++ b/docs/setup-web.mdx @@ -5,6 +5,11 @@ description: Install Copilot with the local browser assistant, then verify a rea This is the recommended interactive installation path. The assistant runs on your computer and prepares the selected workflows and GitHub resources. You review the plan before permission checks or installation changes begin. +Comment callbacks call Copilot's reusable coordinator, keeping dependency setup, +verification and cleanup in one job. Existing runner labels/groups remain visible +in review. Check runner/platform prerequisites and migrate custom bootstrap before +adopting this format; follow the [existing repository upgrade guide](/security-operations/operations/upgrade-rollback#upgrade-an-existing-copilot-repository). + The assistant keeps tutorial, first-workflow and troubleshooting links available throughout the session. They open in another tab and retain your answers. Each question also links to its own reference and has a **Why this matters** explanation. See [Use the documentation](/using-the-docs) for version selection and offline help. ## Before you start diff --git a/scripts/generate-native-verification-workflows.cjs b/scripts/generate-native-verification-workflows.cjs index b8110af05..d47081f62 100644 --- a/scripts/generate-native-verification-workflows.cjs +++ b/scripts/generate-native-verification-workflows.cjs @@ -5,8 +5,12 @@ const yaml = require('js-yaml'); const MAX_REQUESTS = 20; const ACTION = './.git/copilot-verification-setup'; const { SOURCE_ACTION } = require('./prepare-native-source-action.cjs'); -const MARKER = ' # copilot:native-verification:start'; const CALLBACKS = ['copilot_issue_comment.yml', 'copilot_pull_request_comment.yml']; +const { COPILOT_COMMENT_RUNTIME: RUNTIME, COPILOT_COMMENT_REMOTE_WORKFLOW: REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW: SELF_WORKFLOW } = require('../src/domain/copilot_comment_workflow.ts'); +const SELF_ACTION = '$/'; +const SECRET_NAMES = ['PAT', 'OPENCODE_API_KEY', 'OPENAI_API_KEY', 'ANTHROPIC_API_KEY', 'GOOGLE_API_KEY', 'OPENROUTER_API_KEY', 'CURSOR_API_KEY', 'CODEX_API_KEY']; +const BINDINGS = require('../src/infrastructure/copilot_comment_inputs.json'); +const expr = value => '${{ ' + value + ' }}'; function phaseSteps(action, inputAlias = 'copilot-inputs', id = 'copilot') { const steps = []; @@ -38,26 +42,62 @@ function renderSteps(action, alias = 'copilot-inputs', id = 'copilot') { .split('\n').map(line => line ? ` ${line}` : '').join('\n'); } -function generate(file) { - let text = fs.readFileSync(file, 'utf8').split(MARKER)[0].trimEnd() + '\n'; - const action = file.startsWith('setup/') ? 'vypdev/copilot@v3' : SOURCE_ACTION; - if (!file.startsWith('setup/')) { - text = text.replace(' - uses: ./\n', ` - name: Snapshot the Copilot runtime before candidate changes\n id: prepare_native_runtime\n run: node scripts/prepare-native-source-action.cjs\n shell: bash\n\n - uses: ${SOURCE_ACTION}\n`); - if (!text.includes(' COPILOT_NATIVE_RUNTIME_CACHE:')) text = text.replace(' COPILOT_NATIVE_PHASE: prepare\n', ' COPILOT_NATIVE_PHASE: prepare\n COPILOT_NATIVE_RUNTIME_CACHE: ${{ steps.prepare_native_runtime.outputs.path }}\n'); +function commentWorkflow(file, source = false) { + const pr = path.basename(file) === CALLBACKS[1]; + return { + name: `Copilot - ${pr ? 'Pull Request' : 'Issue'} Comment`, + on: { [pr ? 'pull_request_review_comment' : 'issue_comment']: { types: ['created', 'edited'] } }, + jobs: { [pr ? 'copilot-pull-requests' : 'copilot-issues']: { + if: expr(pr ? "(vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN) && github.event.pull_request.head.repo.full_name == github.repository" : "vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN"), + uses: source ? SELF_WORKFLOW : REMOTE_WORKFLOW, + permissions: { checks: 'write', contents: 'read' }, + with: { 'runs-on': JSON.stringify(source ? ['self-hosted', 'codex', 'Linux'] : 'ubuntu-latest'), + ...(source ? { 'issue-managed-branches': 'true', 'pre-branch-sdd': 'true', 'ai-ignore-files': 'build/*,specs/CATALOG.md', 'prepare-source-verification': true } : {}) }, + secrets: Object.fromEntries(SECRET_NAMES.map(name => [name, expr(`secrets.${name}`)])), + } }, + }; +} + +function runtimeWorkflow() { + const inputs = { ...BINDINGS, token: expr('secrets.PAT') }; + for (const key of ['issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files']) { + inputs[key] = BINDINGS[key].replace('${{ ', '${{ inputs.' + key + ' || '); + } + const initial = { name: 'Run Copilot', id: 'copilot', uses: SELF_ACTION, with: inputs, + env: { COPILOT_NATIVE_PHASE: 'prepare', + ...Object.fromEntries(['PROVIDER', 'MODEL_PROVIDER', 'MODEL', 'EFFORT', 'EXECUTABLE'].map(name => ['AGENT_' + name, expr('vars.AGENT_' + name + (name === 'PROVIDER' ? " || 'codex'" : name === 'MODEL_PROVIDER' ? " || 'openai'" : ''))])), + AGENT_ALLOWED_MODEL_PROVIDERS: expr("vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai'"), + AGENT_ALLOWED_MODELS: expr("vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna'"), + ...Object.fromEntries(SECRET_NAMES.filter(name => name !== 'PAT').map(name => [name, expr('secrets.' + name)])), + COPILOT_EVIDENCE_TOKEN: expr('github.token') } }; + initial.env.CURSOR_API_KEY = expr("(vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || ''"); + const preparation = "env.COPILOT_PREPARE_VERIFICATION == 'true'"; + const steps = [ + { name: 'Checkout Repository', uses: 'actions/checkout@v5', with: { 'persist-credentials': false, 'fetch-depth': 0 } }, + { name: 'Prepare repository pnpm', if: preparation, uses: 'pnpm/action-setup@v5', with: { version: '10.12.4', standalone: false, dest: expr('runner.temp') + '/setup-pnpm-' + expr('github.run_id') + '-' + expr('github.run_attempt') + '-' + expr('github.job') } }, + { name: 'Prepare repository Node', if: preparation, uses: 'actions/setup-node@v7', with: { 'node-version': '24.x' } }, + { name: 'Install repository verification dependencies', if: preparation, run: 'pnpm install --frozen-lockfile --ignore-scripts', shell: 'bash' }, + initial, + ...phaseSteps(SELF_ACTION).map(step => ({ ...step, ...(step.with ? { with: inputs } : {}) })), + ]; + return { name: 'Copilot - Comment Runtime', on: { workflow_call: { + inputs: { 'runs-on': { description: 'JSON runner labels or group retained by setup.', type: 'string', default: '"ubuntu-latest"' }, + ...Object.fromEntries(['issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files'].map(key => [key, { description: `Optional ${key} override; otherwise use the caller repository Variable.`, type: 'string', default: '' }])), + 'prepare-source-verification': { description: 'Retain Copilot source-repository verification prerequisites; ignored in consumer repositories.', type: 'boolean', default: false } }, + secrets: Object.fromEntries(SECRET_NAMES.map(name => [name, { required: false }])) } }, + jobs: { copilot: { name: 'Copilot', + if: expr("(vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN) && (github.event_name == 'issue_comment' || (github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.full_name == github.repository))"), + 'runs-on': expr("fromJSON(inputs.runs-on)"), 'timeout-minutes': 120, + permissions: { checks: 'write', contents: 'read' }, + env: { COPILOT_PREPARE_VERIFICATION: expr("github.repository == 'vypdev/copilot' && inputs.prepare-source-verification && vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS != '' && ((contains(github.event.comment.body, '/copilot') && ((contains(github.event.comment.body, 'sync-branch') && !contains(github.event.comment.body, '--dry-run')) || contains(github.event.comment.body, 'implement') || contains(github.event.comment.body, 'fix') || contains(github.event.comment.body, 'remember'))) || (vars.COPILOT_BOT_LOGIN != '' && contains(github.event.comment.body, format('@{0}', vars.COPILOT_BOT_LOGIN)) && !contains(github.event.comment.body, '--dry-run')))" ) }, steps } } }; +} + +function generate() { + for (const directory of ['.github/workflows', 'setup/workflows']) for (const file of CALLBACKS) { + fs.writeFileSync(path.join(directory, file), '# Generated by scripts/generate-native-verification-workflows.cjs\n# Project runtimes: .copilot/verification-prerequisites.json\n# Dependencies: .github/actions/copilot-verification-setup/action.yml\n# https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites\n' + yaml.dump(commentWorkflow(file, directory.startsWith('.github')), { lineWidth: -1, noRefs: true })); } - const start = ` - uses: ${action}\n`; - text = text.replace(/(?: id: copilot\n)+/g, ''); - if (text.includes(start)) text = text.replace(start, ` - uses: ${action}\n id: copilot\n`); - text = text.replace(' with:\n debug:', ' with: &copilot-inputs\n debug:'); - // Distributed templates start with agent inputs rather than debug. - const index = text.indexOf(' id: copilot\n'); - const before = text.slice(0, index); - let operation = text.slice(index); - operation = operation.replace(' with:\n', ' with: &copilot-inputs\n'); - if (!operation.includes(' COPILOT_NATIVE_PHASE: prepare')) operation = operation.replace(' env:\n', ' env:\n COPILOT_NATIVE_PHASE: prepare\n'); - text = before + operation; - fs.writeFileSync(file, `${text}\n${MARKER}\n${renderSteps(action)} # copilot:native-verification:end\n`); + fs.writeFileSync(path.join('.github/workflows', RUNTIME), '# Generated by scripts/generate-native-verification-workflows.cjs\n' + yaml.dump(runtimeWorkflow(), { lineWidth: -1 })); } -if (require.main === module) for (const directory of ['.github/workflows', 'setup/workflows']) for (const file of CALLBACKS) generate(path.join(directory, file)); -module.exports = { MAX_REQUESTS, ACTION, SOURCE_ACTION, CALLBACKS, phaseSteps, renderSteps }; +if (require.main === module) generate(); +module.exports = { MAX_REQUESTS, ACTION, SOURCE_ACTION, CALLBACKS, RUNTIME, SELF_ACTION, REMOTE_WORKFLOW, SELF_WORKFLOW, SECRET_NAMES, BINDINGS, phaseSteps, renderSteps, commentWorkflow, runtimeWorkflow, generate }; diff --git a/scripts/validate-comment-workflows.cjs b/scripts/validate-comment-workflows.cjs new file mode 100644 index 000000000..e40c8dfd5 --- /dev/null +++ b/scripts/validate-comment-workflows.cjs @@ -0,0 +1,33 @@ +const path = require('node:path'); +const { isDeepStrictEqual } = require('node:util'); +const contract = require('./generate-native-verification-workflows.cjs'); +const { copilotCommentRunner, isCopilotCommentRunner } = require('../src/domain/copilot_comment_workflow.ts'); + +function assertCommentWorkflowCaller(file, workflow) { + const source = !file.replaceAll(path.sep, '/').includes('/setup/workflows/'); + const expected = contract.commentWorkflow(path.basename(file), source); + const expectedJob = Object.values(expected.jobs)[0]; + const actualJob = Object.values(workflow.jobs ?? {})[0]; + let route; + try { route = copilotCommentRunner(actualJob); } catch { /* Fixed contract error below. */ } + if (!isCopilotCommentRunner(route)) throw new Error(`${file} native comment runner must be reviewed literal JSON.`); + if (source) { + const labels = typeof route === 'string' || Array.isArray(route) ? route : route.labels; + if (!Array.isArray(labels) || !['self-hosted', 'codex'].every(label => labels.includes(label))) throw new Error(`${file} native source comment caller must retain its self-hosted codex role.`); + } + expectedJob.with['runs-on'] = actualJob.with['runs-on']; + if (actualJob?.if !== expectedJob.if) { + throw new Error(`${file} native comment caller must keep its required bot actor and same-repository PR gate.`); + } + if (!isDeepStrictEqual(workflow, expected)) { + throw new Error(`${file} must pass consistent policy to the native comment coordinator, retaining only its event, bot/fork gate, reviewed runner, scoped Secrets and least-privilege permissions.`); + } +} + +function assertCommentWorkflowRuntime(file, workflow) { + if (!isDeepStrictEqual(workflow, contract.runtimeWorkflow())) { + throw new Error(`${file} must retain the canonical native comment runtime: same-commit Action, input bindings, isolated setup/continue/finish steps, timeout and cleanup.`); + } +} + +module.exports = { assertCommentWorkflowCaller, assertCommentWorkflowRuntime }; diff --git a/scripts/validate-workflow-contract.cjs b/scripts/validate-workflow-contract.cjs index 93bd54194..8bcae2918 100644 --- a/scripts/validate-workflow-contract.cjs +++ b/scripts/validate-workflow-contract.cjs @@ -3,6 +3,8 @@ const { readFileSync, readdirSync } = require('node:fs'); const path = require('node:path'); const yaml = require('js-yaml'); +const commentContract = require('./generate-native-verification-workflows.cjs'); +const { assertCommentWorkflowCaller, assertCommentWorkflowRuntime } = require('./validate-comment-workflows.cjs'); const repositoryRoot = path.resolve(__dirname, '..'); const workflowDirectories = [ @@ -113,6 +115,7 @@ const AGENT_ROLE_INPUTS = Object.freeze(Object.fromEntries( ]]), )); const WORKFLOW_AGENT_ROLES = Object.freeze({ + 'copilot_comment_runtime.yml': ['findings', 'fixer', 'planner', 'reviewer', 'tester'], 'copilot_issue.yml': ['planner'], 'copilot_pull_request.yml': ['planner', 'reviewer'], 'copilot_pull_request_review_state.yml': ['planner', 'reviewer'], @@ -145,6 +148,7 @@ function relativeWorkflow(file) { } function expectedCopilotAction(relativeFile) { + if (path.basename(relativeFile) === commentContract.RUNTIME) return commentContract.SELF_ACTION; if (relativeFile.startsWith('setup/workflows/')) return DISTRIBUTED_COPILOT_ACTION; const native = require('./generate-native-verification-workflows.cjs'); return native.CALLBACKS.includes(path.basename(relativeFile)) ? native.SOURCE_ACTION : './'; @@ -152,7 +156,7 @@ function expectedCopilotAction(relativeFile) { function isCopilotAction(step) { return typeof step?.uses === 'string' - && (step.uses === './' || step.uses === './../.copilot-native-runtime' || /(?:^|\/)copilot@/.test(step.uses)); + && (step.uses === '$/' || step.uses === './' || step.uses === './../.copilot-native-runtime' || /(?:^|\/)copilot@/.test(step.uses)); } function shouldPersistCheckoutCredentials(relativeFile, jobId) { @@ -183,7 +187,7 @@ function assertMajorActionReferences(file, workflow) { } continue; } - if (uses.startsWith('./') || uses.startsWith('docker://')) continue; + if (uses.startsWith('./') || uses.startsWith('$/') || uses.startsWith('docker://')) continue; if (!MAJOR_ACTION_REFERENCE.test(uses)) { throw new Error(`${relativeFile} job ${jobId} action ${uses} must use a major version tag such as owner/action@v1.`); } @@ -340,6 +344,8 @@ function assertPlatformHistoryCheckout(relativeFile, job) { function assertRunner(file, workflow) { const relativeFile = relativeWorkflow(file); + if (path.basename(file) === commentContract.RUNTIME) return assertCommentWorkflowRuntime(file, workflow); + if (commentContract.CALLBACKS.includes(path.basename(file))) return assertCommentWorkflowCaller(file, workflow); if (relativeFile === '.github/workflows/setup_platform_smoke.yml') { const jobIds = Object.keys(workflow.jobs ?? {}).sort(); if (JSON.stringify(jobIds) !== JSON.stringify(['setup-platform-smoke', 'setup-self-hosted-codex-smoke', 'upload-windows-coverage', 'windows-startup-probe'])) { @@ -565,7 +571,7 @@ function assertAgentInstallationPrerequisites(file, workflow) { for (const [jobId, job] of Object.entries(workflow.jobs ?? {})) { const steps = job.steps ?? []; for (const step of steps) { - const repositoryVerificationStep = ['.github/workflows/copilot_issue_comment.yml', '.github/workflows/copilot_pull_request_comment.yml'].includes(relativeFile) + const repositoryVerificationStep = ['.github/workflows/copilot_issue_comment.yml', '.github/workflows/copilot_pull_request_comment.yml', '.github/workflows/copilot_comment_runtime.yml'].includes(relativeFile) && step.if === "env.COPILOT_PREPARE_VERIFICATION == 'true'" && ((step.name === 'Prepare repository Node' && step.uses === 'actions/setup-node@v7' && step.with?.['node-version'] === '24.x') || (step.name === 'Prepare repository pnpm' && step.uses === 'pnpm/action-setup@v5' && step.with?.version === '10.12.4') @@ -596,7 +602,7 @@ function assertAgentWorkflowPermissions(file, workflow) { const relativeFile = relativeWorkflow(file); if (!WORKFLOW_AGENT_ROLES[path.basename(file)]) return; const reviewEvidenceWorkflow = ['copilot_pull_request.yml', 'copilot_pull_request_review_state.yml', - 'copilot_issue_comment.yml', 'copilot_pull_request_comment.yml'].includes(path.basename(file)); + 'copilot_issue_comment.yml', 'copilot_pull_request_comment.yml', 'copilot_comment_runtime.yml'].includes(path.basename(file)); const expectedPermissions = reviewEvidenceWorkflow ? { checks: 'write', contents: 'read' } : { contents: 'read' }; @@ -609,6 +615,10 @@ function assertAgentWorkflowPermissions(file, workflow) { || expectedKeys.some(key => permissions[key] !== expectedPermissions[key])) { throw new Error(`${relativeFile} job ${jobId} must grant GITHUB_TOKEN exactly ${expectedKeys.map(key => `${key}: ${expectedPermissions[key]}`).join(', ')}; mutations use the explicit PAT.`); } + if (commentContract.CALLBACKS.includes(path.basename(file)) && job.uses) { + assertCommentWorkflowCaller(file, workflow); + continue; + } if (reviewEvidenceWorkflow && !(job.steps ?? []).some(step => isCopilotAction(step) && step?.env?.COPILOT_EVIDENCE_TOKEN === '${{ github.token }}')) { throw new Error(`${relativeFile} job ${jobId} must scope COPILOT_EVIDENCE_TOKEN to the Action step for exact-head review Checks.`); @@ -1306,6 +1316,7 @@ function assertQueueWorkflow(file, workflow) { if (BOT_GATED_WORKFLOW_FILES.has(manifest.file) && queueJob.if !== expectedBotGate) { throw new Error(`${relativeFile} queue job ${manifest.jobId} must use the required bot actor${FORK_GATED_WORKFLOW_FILES.has(manifest.file) ? ' and same-repository PR' : ''} gate.`); } + if (commentContract.CALLBACKS.includes(manifest.file)) return assertCommentWorkflowCaller(file, workflow); if (typeof queueJob['timeout-minutes'] !== 'number' || queueJob['timeout-minutes'] < MIN_QUEUE_JOB_TIMEOUT_MINUTES) { throw new Error(`${relativeFile} queue job ${manifest.jobId} must have timeout-minutes >= ${MIN_QUEUE_JOB_TIMEOUT_MINUTES}.`); @@ -1386,6 +1397,7 @@ function assertIssueWorkflowProfileInput(file, workflow) { function assertIssueBranchConfigurationInputs(file, workflow) { if (!WORKFLOW_AGENT_ROLES[path.basename(file)]) return; + if (commentContract.CALLBACKS.includes(path.basename(file))) return assertCommentWorkflowCaller(file, workflow); const relativeFile = relativeWorkflow(file); const distributed = relativeFile.startsWith('setup/workflows/'); const branches = JSON.parse(readFileSync(path.join(repositoryRoot, '.copilot/repository-profile.json'), 'utf8')).branches; @@ -1410,27 +1422,27 @@ function assertIssueBranchConfigurationInputs(file, workflow) { function assertNativeVerificationWorkflow(file, workflow) { const contract = require('./generate-native-verification-workflows.cjs'); - if (!contract.CALLBACKS.includes(path.basename(file))) return; - const relativeFile = relativeWorkflow(file); - const action = expectedCopilotAction(relativeFile); - const jobs = Object.values(workflow.jobs ?? {}).filter(job => (job.steps ?? []).some(step => step.id === 'copilot')); - if (jobs.length !== 1) throw new Error(`${relativeFile} must have exactly one native verification operation.`); - const steps = jobs[0].steps; - const start = steps.findIndex(step => step.id === 'copilot'); - const original = steps[start]; - if (!relativeFile.startsWith('setup/workflows/')) { - const snapshot = steps[start - 1]; - if (snapshot?.id !== 'prepare_native_runtime' || snapshot.run !== 'node scripts/prepare-native-source-action.cjs' - || original.env?.COPILOT_NATIVE_RUNTIME_CACHE !== '${{ steps.prepare_native_runtime.outputs.path }}') throw new Error(`${relativeFile} must snapshot its Action runtime before candidate changes.`); - } - if (original.uses !== action || original.env?.COPILOT_NATIVE_PHASE !== 'prepare') throw new Error(`${relativeFile} must prepare the admitted native operation.`); - const expected = contract.phaseSteps(action).map(step => ({ ...step, ...(step.with ? { with: original.with } : {}) })); - const actual = steps.slice(start + 1); - if (JSON.stringify(actual) !== JSON.stringify(expected)) throw new Error(`${relativeFile} must retain the exact bounded native setup/continuation contract, runtime-only environment, timeout and completion cleanup.`); + if (path.basename(file) === contract.RUNTIME) return assertCommentWorkflowRuntime(file, workflow); + if (contract.CALLBACKS.includes(path.basename(file))) return assertCommentWorkflowCaller(file, workflow); + } function validateWorkflow(file, workflow) { if (!workflow || typeof workflow !== 'object') throw new Error('workflow document is empty.'); + if (commentContract.CALLBACKS.includes(path.basename(file))) { + assertCommentWorkflowCaller(file, workflow); + assertDirectEventTriggers(file, workflow); + return; + } + if (path.basename(file) === commentContract.RUNTIME) { + assertCommentWorkflowRuntime(file, workflow); + assertCopilotActionInputs(file, workflow); + assertNoJobLevelSecrets(file, workflow); + assertAgentWorkflowPermissions(file, workflow); + assertAgentInputs(file, workflow); + assertRepositoryLocaleInputs(file, workflow); + return; + } assertNativeVerificationWorkflow(file, workflow); assertManualRepoWiseWorkflow(file, workflow); assertDirectEventTriggers(file, workflow); diff --git a/setup/workflows/copilot_issue_comment.yml b/setup/workflows/copilot_issue_comment.yml index ea8c42d0a..dd360d03e 100644 --- a/setup/workflows/copilot_issue_comment.yml +++ b/setup/workflows/copilot_issue_comment.yml @@ -1,692 +1,28 @@ +# Generated by scripts/generate-native-verification-workflows.cjs +# Project runtimes: .copilot/verification-prerequisites.json +# Dependencies: .github/actions/copilot-verification-setup/action.yml +# https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites name: Copilot - Issue Comment - -on: +'on': issue_comment: - types: [created, edited] - + types: + - created + - edited jobs: copilot-issues: if: ${{ vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN }} - name: Copilot - Issue Comment - runs-on: ubuntu-latest - timeout-minutes: 120 + uses: vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3 permissions: checks: write contents: read - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - with: - persist-credentials: false - fetch-depth: 0 - - # Before Copilot, provision project runtimes/dependencies in this same job when - # repository verification is configured. A separate CI job does not prepare it. - # Declare reviewed versions in .copilot/verification-prerequisites.json. - # Optional trusted-main setup: VERIFICATION_SETUP=true and .github/actions/copilot-verification-setup/action.yml. - # https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites - - uses: vypdev/copilot@v3 - id: copilot - with: &copilot-inputs - repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }} - issues-locale: ${{ vars.ISSUES_LOCALE || '' }} - pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }} - ai-ignore-files: ${{ vars.AI_IGNORE_FILES || 'build/*' }} - debug: ${{ vars.DEBUG }} - main-branch: ${{ vars.MAIN_BRANCH || 'master' }} - development-branch: ${{ vars.DEVELOPMENT_BRANCH || 'develop' }} - feature-tree: ${{ vars.FEATURE_TREE || 'feature' }} - bugfix-tree: ${{ vars.BUGFIX_TREE || 'bugfix' }} - hotfix-tree: ${{ vars.HOTFIX_TREE || 'hotfix' }} - release-tree: ${{ vars.RELEASE_TREE || 'release' }} - docs-tree: ${{ vars.DOCS_TREE || 'docs' }} - chore-tree: ${{ vars.CHORE_TREE || 'chore' }} - issue-managed-branches: ${{ vars.ISSUE_MANAGED_BRANCHES || 'true' }} - pre-branch-sdd: ${{ vars.PRE_BRANCH_SDD || 'false' }} - verification-setup: ${{ vars.VERIFICATION_SETUP || 'false' }} - issue-workflow-profile: ${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }} - reopen-issue-on-push: ${{ vars.REOPEN_ISSUE_ON_PUSH || 'true' }} - desired-assignees-count: ${{ vars.DESIRED_ASSIGNEES_COUNT || '1' }} - desired-reviewers-count: ${{ vars.DESIRED_REVIEWERS_COUNT || '1' }} - commit-prefix-transforms: ${{ vars.COMMIT_PREFIX_TRANSFORMS || 'replace-slash' }} - ai-pull-request-description-mode: ${{ vars.AI_PULL_REQUEST_DESCRIPTION_MODE || 'replace' }} - ai-members-only: ${{ vars.AI_MEMBERS_ONLY || 'false' }} - ai-include-reasoning: ${{ vars.AI_INCLUDE_REASONING || 'false' }} - bugbot-severity: ${{ vars.BUGBOT_SEVERITY || 'low' }} - bugbot-comment-limit: ${{ vars.BUGBOT_COMMENT_LIMIT || '20' }} - bugbot-fix-verify-commands: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }} - bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }} - bugbot-effort: ${{ vars.BUGBOT_EFFORT || 'smart' }} - bugbot-review-drafts: ${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }} - bugbot-trace-rules: ${{ vars.BUGBOT_TRACE_RULES || 'false' }} - bugbot-suggested-changes: ${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }} - bugbot-telemetry: ${{ vars.BUGBOT_TELEMETRY || 'true' }} - bugbot-fail-on-unresolved: ${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }} - bugbot-organization-rules: ${{ vars.BUGBOT_ORGANIZATION_RULES }} - project-column-issue-created: ${{ vars.PROJECT_COLUMN_ISSUE_CREATED || 'Todo' }} - project-column-pull-request-created: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_CREATED || 'In Progress' }} - project-column-issue-in-progress: ${{ vars.PROJECT_COLUMN_ISSUE_IN_PROGRESS || 'In Progress' }} - project-column-pull-request-in-progress: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_IN_PROGRESS || 'In Progress' }} - agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }} - agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }} - agent-effort: ${{ vars.AGENT_EFFORT }} - agent-executable: ${{ vars.AGENT_EXECUTABLE }} - findings-provider: ${{ vars.FINDINGS_PROVIDER }} - findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }} - findings-model: ${{ vars.FINDINGS_MODEL }} - findings-effort: ${{ vars.FINDINGS_EFFORT }} - findings-executable: ${{ vars.FINDINGS_EXECUTABLE }} - fixer-provider: ${{ vars.FIXER_PROVIDER }} - fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }} - fixer-model: ${{ vars.FIXER_MODEL }} - fixer-effort: ${{ vars.FIXER_EFFORT }} - fixer-executable: ${{ vars.FIXER_EXECUTABLE }} - planner-provider: ${{ vars.PLANNER_PROVIDER }} - planner-model-provider: ${{ vars.PLANNER_MODEL_PROVIDER }} - planner-model: ${{ vars.PLANNER_MODEL }} - planner-effort: ${{ vars.PLANNER_EFFORT }} - planner-executable: ${{ vars.PLANNER_EXECUTABLE }} - reviewer-provider: ${{ vars.REVIEWER_PROVIDER }} - reviewer-model-provider: ${{ vars.REVIEWER_MODEL_PROVIDER }} - reviewer-model: ${{ vars.REVIEWER_MODEL }} - reviewer-effort: ${{ vars.REVIEWER_EFFORT }} - reviewer-executable: ${{ vars.REVIEWER_EXECUTABLE }} - tester-provider: ${{ vars.TESTER_PROVIDER }} - tester-model-provider: ${{ vars.TESTER_MODEL_PROVIDER }} - tester-model: ${{ vars.TESTER_MODEL }} - tester-effort: ${{ vars.TESTER_EFFORT }} - tester-executable: ${{ vars.TESTER_EXECUTABLE }} - project-ids: ${{ vars.PROJECT_IDS }} - token: ${{ secrets.PAT }} - env: - COPILOT_NATIVE_PHASE: prepare - AGENT_PROVIDER: ${{ vars.AGENT_PROVIDER || 'codex' }} - AGENT_MODEL_PROVIDER: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - AGENT_MODEL: ${{ vars.AGENT_MODEL }} - AGENT_EFFORT: ${{ vars.AGENT_EFFORT }} - AGENT_ALLOWED_MODEL_PROVIDERS: ${{ vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai' }} - AGENT_ALLOWED_MODELS: ${{ vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna' }} - AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} - CURSOR_API_KEY: ${{ (vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || '' }} - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - COPILOT_EVIDENCE_TOKEN: ${{ github.token }} - - # copilot:native-verification:start - - name: Prepare repository verification 1 - id: verification_setup_1 - if: ${{ !cancelled() && steps.copilot.outcome == 'success' && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.copilot.outputs.verification-home }} - USERPROFILE: ${{ steps.copilot.outputs.verification-userprofile }} - APPDATA: ${{ steps.copilot.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.copilot.outputs.verification-localappdata }} - PATH: ${{ steps.copilot.outputs.verification-path }} - JAVA_HOME: ${{ steps.copilot.outputs.verification-java_home }} - TMP: ${{ steps.copilot.outputs.verification-tmp }} - TEMP: ${{ steps.copilot.outputs.verification-temp }} - TMPDIR: ${{ steps.copilot.outputs.verification-tmpdir }} - - name: Continue repository verification 1 - id: verification_continue_1 - if: ${{ always() && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.copilot.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_1.outcome }} - - name: Prepare repository verification 2 - id: verification_setup_2 - if: ${{ !cancelled() && steps.verification_continue_1.outcome == 'success' && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_1.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_1.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_1.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_1.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_1.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_1.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_1.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_1.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_1.outputs.verification-tmpdir }} - - name: Continue repository verification 2 - id: verification_continue_2 - if: ${{ always() && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_1.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_2.outcome }} - - name: Prepare repository verification 3 - id: verification_setup_3 - if: ${{ !cancelled() && steps.verification_continue_2.outcome == 'success' && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_2.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_2.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_2.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_2.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_2.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_2.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_2.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_2.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_2.outputs.verification-tmpdir }} - - name: Continue repository verification 3 - id: verification_continue_3 - if: ${{ always() && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_2.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_3.outcome }} - - name: Prepare repository verification 4 - id: verification_setup_4 - if: ${{ !cancelled() && steps.verification_continue_3.outcome == 'success' && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_3.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_3.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_3.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_3.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_3.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_3.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_3.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_3.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_3.outputs.verification-tmpdir }} - - name: Continue repository verification 4 - id: verification_continue_4 - if: ${{ always() && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_3.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_4.outcome }} - - name: Prepare repository verification 5 - id: verification_setup_5 - if: ${{ !cancelled() && steps.verification_continue_4.outcome == 'success' && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_4.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_4.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_4.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_4.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_4.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_4.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_4.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_4.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_4.outputs.verification-tmpdir }} - - name: Continue repository verification 5 - id: verification_continue_5 - if: ${{ always() && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_4.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_5.outcome }} - - name: Prepare repository verification 6 - id: verification_setup_6 - if: ${{ !cancelled() && steps.verification_continue_5.outcome == 'success' && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_5.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_5.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_5.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_5.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_5.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_5.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_5.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_5.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_5.outputs.verification-tmpdir }} - - name: Continue repository verification 6 - id: verification_continue_6 - if: ${{ always() && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_5.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_6.outcome }} - - name: Prepare repository verification 7 - id: verification_setup_7 - if: ${{ !cancelled() && steps.verification_continue_6.outcome == 'success' && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_6.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_6.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_6.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_6.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_6.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_6.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_6.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_6.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_6.outputs.verification-tmpdir }} - - name: Continue repository verification 7 - id: verification_continue_7 - if: ${{ always() && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_6.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_7.outcome }} - - name: Prepare repository verification 8 - id: verification_setup_8 - if: ${{ !cancelled() && steps.verification_continue_7.outcome == 'success' && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_7.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_7.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_7.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_7.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_7.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_7.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_7.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_7.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_7.outputs.verification-tmpdir }} - - name: Continue repository verification 8 - id: verification_continue_8 - if: ${{ always() && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_7.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_8.outcome }} - - name: Prepare repository verification 9 - id: verification_setup_9 - if: ${{ !cancelled() && steps.verification_continue_8.outcome == 'success' && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_8.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_8.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_8.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_8.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_8.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_8.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_8.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_8.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_8.outputs.verification-tmpdir }} - - name: Continue repository verification 9 - id: verification_continue_9 - if: ${{ always() && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_8.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_9.outcome }} - - name: Prepare repository verification 10 - id: verification_setup_10 - if: ${{ !cancelled() && steps.verification_continue_9.outcome == 'success' && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_9.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_9.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_9.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_9.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_9.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_9.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_9.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_9.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_9.outputs.verification-tmpdir }} - - name: Continue repository verification 10 - id: verification_continue_10 - if: ${{ always() && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_9.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_10.outcome }} - - name: Prepare repository verification 11 - id: verification_setup_11 - if: ${{ !cancelled() && steps.verification_continue_10.outcome == 'success' && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_10.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_10.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_10.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_10.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_10.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_10.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_10.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_10.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_10.outputs.verification-tmpdir }} - - name: Continue repository verification 11 - id: verification_continue_11 - if: ${{ always() && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_10.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_11.outcome }} - - name: Prepare repository verification 12 - id: verification_setup_12 - if: ${{ !cancelled() && steps.verification_continue_11.outcome == 'success' && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_11.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_11.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_11.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_11.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_11.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_11.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_11.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_11.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_11.outputs.verification-tmpdir }} - - name: Continue repository verification 12 - id: verification_continue_12 - if: ${{ always() && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_11.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_12.outcome }} - - name: Prepare repository verification 13 - id: verification_setup_13 - if: ${{ !cancelled() && steps.verification_continue_12.outcome == 'success' && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_12.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_12.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_12.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_12.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_12.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_12.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_12.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_12.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_12.outputs.verification-tmpdir }} - - name: Continue repository verification 13 - id: verification_continue_13 - if: ${{ always() && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_12.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_13.outcome }} - - name: Prepare repository verification 14 - id: verification_setup_14 - if: ${{ !cancelled() && steps.verification_continue_13.outcome == 'success' && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_13.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_13.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_13.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_13.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_13.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_13.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_13.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_13.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_13.outputs.verification-tmpdir }} - - name: Continue repository verification 14 - id: verification_continue_14 - if: ${{ always() && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_13.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_14.outcome }} - - name: Prepare repository verification 15 - id: verification_setup_15 - if: ${{ !cancelled() && steps.verification_continue_14.outcome == 'success' && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_14.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_14.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_14.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_14.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_14.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_14.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_14.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_14.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_14.outputs.verification-tmpdir }} - - name: Continue repository verification 15 - id: verification_continue_15 - if: ${{ always() && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_14.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_15.outcome }} - - name: Prepare repository verification 16 - id: verification_setup_16 - if: ${{ !cancelled() && steps.verification_continue_15.outcome == 'success' && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_15.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_15.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_15.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_15.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_15.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_15.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_15.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_15.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_15.outputs.verification-tmpdir }} - - name: Continue repository verification 16 - id: verification_continue_16 - if: ${{ always() && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_15.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_16.outcome }} - - name: Prepare repository verification 17 - id: verification_setup_17 - if: ${{ !cancelled() && steps.verification_continue_16.outcome == 'success' && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_16.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_16.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_16.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_16.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_16.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_16.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_16.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_16.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_16.outputs.verification-tmpdir }} - - name: Continue repository verification 17 - id: verification_continue_17 - if: ${{ always() && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_16.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_17.outcome }} - - name: Prepare repository verification 18 - id: verification_setup_18 - if: ${{ !cancelled() && steps.verification_continue_17.outcome == 'success' && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_17.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_17.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_17.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_17.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_17.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_17.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_17.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_17.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_17.outputs.verification-tmpdir }} - - name: Continue repository verification 18 - id: verification_continue_18 - if: ${{ always() && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_17.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_18.outcome }} - - name: Prepare repository verification 19 - id: verification_setup_19 - if: ${{ !cancelled() && steps.verification_continue_18.outcome == 'success' && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_18.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_18.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_18.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_18.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_18.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_18.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_18.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_18.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_18.outputs.verification-tmpdir }} - - name: Continue repository verification 19 - id: verification_continue_19 - if: ${{ always() && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_18.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_19.outcome }} - - name: Prepare repository verification 20 - id: verification_setup_20 - if: ${{ !cancelled() && steps.verification_continue_19.outcome == 'success' && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_19.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_19.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_19.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_19.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_19.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_19.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_19.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_19.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_19.outputs.verification-tmpdir }} - - name: Continue repository verification 20 - id: verification_continue_20 - if: ${{ always() && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_19.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_20.outcome }} - - name: Complete repository verification - id: verification_complete - if: ${{ always() && steps.copilot.outputs.verification-ticket != '' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: finish - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - # copilot:native-verification:end + with: + runs-on: '"ubuntu-latest"' + secrets: + PAT: ${{ secrets.PAT }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} diff --git a/setup/workflows/copilot_pull_request_comment.yml b/setup/workflows/copilot_pull_request_comment.yml index c5e05f433..455fa34a6 100644 --- a/setup/workflows/copilot_pull_request_comment.yml +++ b/setup/workflows/copilot_pull_request_comment.yml @@ -1,692 +1,28 @@ +# Generated by scripts/generate-native-verification-workflows.cjs +# Project runtimes: .copilot/verification-prerequisites.json +# Dependencies: .github/actions/copilot-verification-setup/action.yml +# https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites name: Copilot - Pull Request Comment - -on: +'on': pull_request_review_comment: - types: [created, edited] - + types: + - created + - edited jobs: copilot-pull-requests: if: ${{ (vars.COPILOT_BOT_LOGIN == '' || github.actor != vars.COPILOT_BOT_LOGIN) && github.event.pull_request.head.repo.full_name == github.repository }} - name: Copilot - Pull Request Comment - runs-on: ubuntu-latest - timeout-minutes: 120 + uses: vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3 permissions: checks: write contents: read - steps: - - name: Checkout Repository - uses: actions/checkout@v5 - with: - persist-credentials: false - fetch-depth: 0 - - # Before Copilot, provision project runtimes/dependencies in this same job when - # repository verification is configured. A separate CI job does not prepare it. - # Declare reviewed versions in .copilot/verification-prerequisites.json. - # Optional trusted-main setup: VERIFICATION_SETUP=true and .github/actions/copilot-verification-setup/action.yml. - # https://docs.page/vypdev/copilot/security-operations/operations/verification#repository-verification-prerequisites - - uses: vypdev/copilot@v3 - id: copilot - with: &copilot-inputs - repository-locale: ${{ vars.REPOSITORY_LOCALE || 'en-US' }} - issues-locale: ${{ vars.ISSUES_LOCALE || '' }} - pull-requests-locale: ${{ vars.PULL_REQUESTS_LOCALE || '' }} - issue-workflow-profile: ${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }} - ai-ignore-files: ${{ vars.AI_IGNORE_FILES || 'build/*' }} - debug: ${{ vars.DEBUG }} - main-branch: ${{ vars.MAIN_BRANCH || 'master' }} - development-branch: ${{ vars.DEVELOPMENT_BRANCH || 'develop' }} - feature-tree: ${{ vars.FEATURE_TREE || 'feature' }} - bugfix-tree: ${{ vars.BUGFIX_TREE || 'bugfix' }} - hotfix-tree: ${{ vars.HOTFIX_TREE || 'hotfix' }} - release-tree: ${{ vars.RELEASE_TREE || 'release' }} - docs-tree: ${{ vars.DOCS_TREE || 'docs' }} - chore-tree: ${{ vars.CHORE_TREE || 'chore' }} - issue-managed-branches: ${{ vars.ISSUE_MANAGED_BRANCHES || 'true' }} - pre-branch-sdd: ${{ vars.PRE_BRANCH_SDD || 'false' }} - verification-setup: ${{ vars.VERIFICATION_SETUP || 'false' }} - reopen-issue-on-push: ${{ vars.REOPEN_ISSUE_ON_PUSH || 'true' }} - desired-assignees-count: ${{ vars.DESIRED_ASSIGNEES_COUNT || '1' }} - desired-reviewers-count: ${{ vars.DESIRED_REVIEWERS_COUNT || '1' }} - commit-prefix-transforms: ${{ vars.COMMIT_PREFIX_TRANSFORMS || 'replace-slash' }} - ai-pull-request-description-mode: ${{ vars.AI_PULL_REQUEST_DESCRIPTION_MODE || 'replace' }} - ai-members-only: ${{ vars.AI_MEMBERS_ONLY || 'false' }} - ai-include-reasoning: ${{ vars.AI_INCLUDE_REASONING || 'false' }} - bugbot-severity: ${{ vars.BUGBOT_SEVERITY || 'low' }} - bugbot-comment-limit: ${{ vars.BUGBOT_COMMENT_LIMIT || '20' }} - bugbot-fix-verify-commands: ${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }} - bugbot-dry-run: ${{ vars.BUGBOT_DRY_RUN || 'false' }} - bugbot-effort: ${{ vars.BUGBOT_EFFORT || 'smart' }} - bugbot-review-drafts: ${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }} - bugbot-trace-rules: ${{ vars.BUGBOT_TRACE_RULES || 'false' }} - bugbot-suggested-changes: ${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }} - bugbot-telemetry: ${{ vars.BUGBOT_TELEMETRY || 'true' }} - bugbot-fail-on-unresolved: ${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }} - bugbot-organization-rules: ${{ vars.BUGBOT_ORGANIZATION_RULES }} - project-column-issue-created: ${{ vars.PROJECT_COLUMN_ISSUE_CREATED || 'Todo' }} - project-column-pull-request-created: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_CREATED || 'In Progress' }} - project-column-issue-in-progress: ${{ vars.PROJECT_COLUMN_ISSUE_IN_PROGRESS || 'In Progress' }} - project-column-pull-request-in-progress: ${{ vars.PROJECT_COLUMN_PULL_REQUEST_IN_PROGRESS || 'In Progress' }} - agent-provider: ${{ vars.AGENT_PROVIDER || 'codex' }} - agent-model-provider: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - agent-model: ${{ vars.AGENT_MODEL || 'gpt-6-luna' }} - agent-effort: ${{ vars.AGENT_EFFORT }} - agent-executable: ${{ vars.AGENT_EXECUTABLE }} - findings-provider: ${{ vars.FINDINGS_PROVIDER }} - findings-model-provider: ${{ vars.FINDINGS_MODEL_PROVIDER }} - findings-model: ${{ vars.FINDINGS_MODEL }} - findings-effort: ${{ vars.FINDINGS_EFFORT }} - findings-executable: ${{ vars.FINDINGS_EXECUTABLE }} - fixer-provider: ${{ vars.FIXER_PROVIDER }} - fixer-model-provider: ${{ vars.FIXER_MODEL_PROVIDER }} - fixer-model: ${{ vars.FIXER_MODEL }} - fixer-effort: ${{ vars.FIXER_EFFORT }} - fixer-executable: ${{ vars.FIXER_EXECUTABLE }} - reviewer-provider: ${{ vars.REVIEWER_PROVIDER }} - reviewer-model-provider: ${{ vars.REVIEWER_MODEL_PROVIDER }} - reviewer-model: ${{ vars.REVIEWER_MODEL }} - reviewer-effort: ${{ vars.REVIEWER_EFFORT }} - reviewer-executable: ${{ vars.REVIEWER_EXECUTABLE }} - planner-provider: ${{ vars.PLANNER_PROVIDER }} - planner-model-provider: ${{ vars.PLANNER_MODEL_PROVIDER }} - planner-model: ${{ vars.PLANNER_MODEL }} - planner-effort: ${{ vars.PLANNER_EFFORT }} - planner-executable: ${{ vars.PLANNER_EXECUTABLE }} - tester-provider: ${{ vars.TESTER_PROVIDER }} - tester-model-provider: ${{ vars.TESTER_MODEL_PROVIDER }} - tester-model: ${{ vars.TESTER_MODEL }} - tester-effort: ${{ vars.TESTER_EFFORT }} - tester-executable: ${{ vars.TESTER_EXECUTABLE }} - project-ids: ${{ vars.PROJECT_IDS }} - token: ${{ secrets.PAT }} - env: - COPILOT_NATIVE_PHASE: prepare - AGENT_PROVIDER: ${{ vars.AGENT_PROVIDER || 'codex' }} - AGENT_MODEL_PROVIDER: ${{ vars.AGENT_MODEL_PROVIDER || 'openai' }} - AGENT_MODEL: ${{ vars.AGENT_MODEL }} - AGENT_EFFORT: ${{ vars.AGENT_EFFORT }} - AGENT_ALLOWED_MODEL_PROVIDERS: ${{ vars.AGENT_ALLOWED_MODEL_PROVIDERS || 'openai' }} - AGENT_ALLOWED_MODELS: ${{ vars.AGENT_ALLOWED_MODELS || 'openai/gpt-6-luna' }} - AGENT_EXECUTABLE: ${{ vars.AGENT_EXECUTABLE }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} - CURSOR_API_KEY: ${{ (vars.AGENT_PROVIDER == 'cursor' || vars.FINDINGS_PROVIDER == 'cursor' || vars.FIXER_PROVIDER == 'cursor' || vars.PLANNER_PROVIDER == 'cursor' || vars.REVIEWER_PROVIDER == 'cursor' || vars.TESTER_PROVIDER == 'cursor') && secrets.CURSOR_API_KEY || '' }} - CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} - COPILOT_EVIDENCE_TOKEN: ${{ github.token }} - - # copilot:native-verification:start - - name: Prepare repository verification 1 - id: verification_setup_1 - if: ${{ !cancelled() && steps.copilot.outcome == 'success' && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.copilot.outputs.verification-home }} - USERPROFILE: ${{ steps.copilot.outputs.verification-userprofile }} - APPDATA: ${{ steps.copilot.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.copilot.outputs.verification-localappdata }} - PATH: ${{ steps.copilot.outputs.verification-path }} - JAVA_HOME: ${{ steps.copilot.outputs.verification-java_home }} - TMP: ${{ steps.copilot.outputs.verification-tmp }} - TEMP: ${{ steps.copilot.outputs.verification-temp }} - TMPDIR: ${{ steps.copilot.outputs.verification-tmpdir }} - - name: Continue repository verification 1 - id: verification_continue_1 - if: ${{ always() && steps.copilot.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.copilot.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_1.outcome }} - - name: Prepare repository verification 2 - id: verification_setup_2 - if: ${{ !cancelled() && steps.verification_continue_1.outcome == 'success' && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_1.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_1.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_1.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_1.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_1.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_1.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_1.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_1.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_1.outputs.verification-tmpdir }} - - name: Continue repository verification 2 - id: verification_continue_2 - if: ${{ always() && steps.verification_continue_1.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_1.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_2.outcome }} - - name: Prepare repository verification 3 - id: verification_setup_3 - if: ${{ !cancelled() && steps.verification_continue_2.outcome == 'success' && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_2.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_2.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_2.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_2.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_2.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_2.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_2.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_2.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_2.outputs.verification-tmpdir }} - - name: Continue repository verification 3 - id: verification_continue_3 - if: ${{ always() && steps.verification_continue_2.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_2.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_3.outcome }} - - name: Prepare repository verification 4 - id: verification_setup_4 - if: ${{ !cancelled() && steps.verification_continue_3.outcome == 'success' && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_3.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_3.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_3.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_3.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_3.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_3.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_3.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_3.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_3.outputs.verification-tmpdir }} - - name: Continue repository verification 4 - id: verification_continue_4 - if: ${{ always() && steps.verification_continue_3.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_3.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_4.outcome }} - - name: Prepare repository verification 5 - id: verification_setup_5 - if: ${{ !cancelled() && steps.verification_continue_4.outcome == 'success' && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_4.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_4.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_4.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_4.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_4.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_4.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_4.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_4.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_4.outputs.verification-tmpdir }} - - name: Continue repository verification 5 - id: verification_continue_5 - if: ${{ always() && steps.verification_continue_4.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_4.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_5.outcome }} - - name: Prepare repository verification 6 - id: verification_setup_6 - if: ${{ !cancelled() && steps.verification_continue_5.outcome == 'success' && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_5.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_5.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_5.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_5.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_5.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_5.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_5.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_5.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_5.outputs.verification-tmpdir }} - - name: Continue repository verification 6 - id: verification_continue_6 - if: ${{ always() && steps.verification_continue_5.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_5.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_6.outcome }} - - name: Prepare repository verification 7 - id: verification_setup_7 - if: ${{ !cancelled() && steps.verification_continue_6.outcome == 'success' && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_6.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_6.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_6.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_6.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_6.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_6.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_6.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_6.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_6.outputs.verification-tmpdir }} - - name: Continue repository verification 7 - id: verification_continue_7 - if: ${{ always() && steps.verification_continue_6.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_6.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_7.outcome }} - - name: Prepare repository verification 8 - id: verification_setup_8 - if: ${{ !cancelled() && steps.verification_continue_7.outcome == 'success' && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_7.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_7.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_7.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_7.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_7.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_7.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_7.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_7.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_7.outputs.verification-tmpdir }} - - name: Continue repository verification 8 - id: verification_continue_8 - if: ${{ always() && steps.verification_continue_7.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_7.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_8.outcome }} - - name: Prepare repository verification 9 - id: verification_setup_9 - if: ${{ !cancelled() && steps.verification_continue_8.outcome == 'success' && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_8.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_8.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_8.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_8.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_8.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_8.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_8.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_8.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_8.outputs.verification-tmpdir }} - - name: Continue repository verification 9 - id: verification_continue_9 - if: ${{ always() && steps.verification_continue_8.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_8.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_9.outcome }} - - name: Prepare repository verification 10 - id: verification_setup_10 - if: ${{ !cancelled() && steps.verification_continue_9.outcome == 'success' && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_9.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_9.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_9.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_9.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_9.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_9.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_9.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_9.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_9.outputs.verification-tmpdir }} - - name: Continue repository verification 10 - id: verification_continue_10 - if: ${{ always() && steps.verification_continue_9.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_9.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_10.outcome }} - - name: Prepare repository verification 11 - id: verification_setup_11 - if: ${{ !cancelled() && steps.verification_continue_10.outcome == 'success' && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_10.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_10.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_10.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_10.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_10.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_10.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_10.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_10.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_10.outputs.verification-tmpdir }} - - name: Continue repository verification 11 - id: verification_continue_11 - if: ${{ always() && steps.verification_continue_10.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_10.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_11.outcome }} - - name: Prepare repository verification 12 - id: verification_setup_12 - if: ${{ !cancelled() && steps.verification_continue_11.outcome == 'success' && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_11.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_11.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_11.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_11.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_11.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_11.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_11.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_11.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_11.outputs.verification-tmpdir }} - - name: Continue repository verification 12 - id: verification_continue_12 - if: ${{ always() && steps.verification_continue_11.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_11.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_12.outcome }} - - name: Prepare repository verification 13 - id: verification_setup_13 - if: ${{ !cancelled() && steps.verification_continue_12.outcome == 'success' && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_12.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_12.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_12.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_12.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_12.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_12.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_12.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_12.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_12.outputs.verification-tmpdir }} - - name: Continue repository verification 13 - id: verification_continue_13 - if: ${{ always() && steps.verification_continue_12.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_12.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_13.outcome }} - - name: Prepare repository verification 14 - id: verification_setup_14 - if: ${{ !cancelled() && steps.verification_continue_13.outcome == 'success' && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_13.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_13.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_13.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_13.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_13.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_13.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_13.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_13.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_13.outputs.verification-tmpdir }} - - name: Continue repository verification 14 - id: verification_continue_14 - if: ${{ always() && steps.verification_continue_13.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_13.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_14.outcome }} - - name: Prepare repository verification 15 - id: verification_setup_15 - if: ${{ !cancelled() && steps.verification_continue_14.outcome == 'success' && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_14.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_14.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_14.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_14.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_14.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_14.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_14.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_14.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_14.outputs.verification-tmpdir }} - - name: Continue repository verification 15 - id: verification_continue_15 - if: ${{ always() && steps.verification_continue_14.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_14.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_15.outcome }} - - name: Prepare repository verification 16 - id: verification_setup_16 - if: ${{ !cancelled() && steps.verification_continue_15.outcome == 'success' && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_15.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_15.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_15.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_15.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_15.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_15.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_15.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_15.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_15.outputs.verification-tmpdir }} - - name: Continue repository verification 16 - id: verification_continue_16 - if: ${{ always() && steps.verification_continue_15.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_15.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_16.outcome }} - - name: Prepare repository verification 17 - id: verification_setup_17 - if: ${{ !cancelled() && steps.verification_continue_16.outcome == 'success' && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_16.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_16.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_16.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_16.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_16.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_16.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_16.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_16.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_16.outputs.verification-tmpdir }} - - name: Continue repository verification 17 - id: verification_continue_17 - if: ${{ always() && steps.verification_continue_16.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_16.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_17.outcome }} - - name: Prepare repository verification 18 - id: verification_setup_18 - if: ${{ !cancelled() && steps.verification_continue_17.outcome == 'success' && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_17.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_17.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_17.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_17.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_17.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_17.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_17.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_17.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_17.outputs.verification-tmpdir }} - - name: Continue repository verification 18 - id: verification_continue_18 - if: ${{ always() && steps.verification_continue_17.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_17.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_18.outcome }} - - name: Prepare repository verification 19 - id: verification_setup_19 - if: ${{ !cancelled() && steps.verification_continue_18.outcome == 'success' && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_18.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_18.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_18.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_18.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_18.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_18.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_18.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_18.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_18.outputs.verification-tmpdir }} - - name: Continue repository verification 19 - id: verification_continue_19 - if: ${{ always() && steps.verification_continue_18.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_18.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_19.outcome }} - - name: Prepare repository verification 20 - id: verification_setup_20 - if: ${{ !cancelled() && steps.verification_continue_19.outcome == 'success' && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: ./.git/copilot-verification-setup - timeout-minutes: 5 - env: - HOME: ${{ steps.verification_continue_19.outputs.verification-home }} - USERPROFILE: ${{ steps.verification_continue_19.outputs.verification-userprofile }} - APPDATA: ${{ steps.verification_continue_19.outputs.verification-appdata }} - LOCALAPPDATA: ${{ steps.verification_continue_19.outputs.verification-localappdata }} - PATH: ${{ steps.verification_continue_19.outputs.verification-path }} - JAVA_HOME: ${{ steps.verification_continue_19.outputs.verification-java_home }} - TMP: ${{ steps.verification_continue_19.outputs.verification-tmp }} - TEMP: ${{ steps.verification_continue_19.outputs.verification-temp }} - TMPDIR: ${{ steps.verification_continue_19.outputs.verification-tmpdir }} - - name: Continue repository verification 20 - id: verification_continue_20 - if: ${{ always() && steps.verification_continue_19.outputs.verification-setup-pending == 'true' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: continue - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - COPILOT_NATIVE_REQUEST: ${{ steps.verification_continue_19.outputs.verification-request }} - COPILOT_NATIVE_OUTCOME: ${{ steps.verification_setup_20.outcome }} - - name: Complete repository verification - id: verification_complete - if: ${{ always() && steps.copilot.outputs.verification-ticket != '' }} - uses: vypdev/copilot@v3 - with: *copilot-inputs - env: - COPILOT_NATIVE_PHASE: finish - COPILOT_NATIVE_SOURCE: ${{ steps.copilot.outputs.verification-source }} - COPILOT_NATIVE_DIGEST: ${{ steps.copilot.outputs.verification-digest }} - COPILOT_NATIVE_GIT: ${{ steps.copilot.outputs.verification-git }} - COPILOT_NATIVE_TICKET: ${{ steps.copilot.outputs.verification-ticket }} - # copilot:native-verification:end + with: + runs-on: '"ubuntu-latest"' + secrets: + PAT: ${{ secrets.PAT }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }} diff --git a/specs/CATALOG.md b/specs/CATALOG.md index 6818dabd1..14cfe2eaa 100644 --- a/specs/CATALOG.md +++ b/specs/CATALOG.md @@ -16,7 +16,7 @@ debt or convert unknown historic intent into a design decision. | `bugbot-review-state-reconciliation` | Implemented | Reconcile review snapshots, findings, threads, comments, and check conclusions | [Bugbot review-state reconciliation](./bugbot-review-state-reconciliation.md) | 70 paths · 2026-10-21 | | `execution-lifecycle` | Implemented | Shared GitHub Action lifecycle from event admission through durable user-facing results | [Execution admission, queueing, routing, and result publication](./execution-admission-queue-and-publication.md) + 3 companion | 104 paths · 2026-10-21 | | `architecture-quality-hardening` | Implemented | Close verified concurrency, error-contract, context-coupling, fan-out, setup/doctor, and provider-policy risks in dependency order | [Architecture quality and scalability hardening](./architecture-quality-and-scalability-hardening.md) + 1 companion | 72 paths · 2026-10-13 | -| `setup-and-doctor` | Implemented | Plan, validate, provision, and audit a repository installation without exposing credentials | [Setup, configuration, credentials, and doctor](./setup-configuration-credentials-and-doctor.md) + 5 companion | 328 paths · 2026-10-20 | +| `setup-and-doctor` | Implemented | Plan, validate, provision, and audit a repository installation without exposing credentials | [Setup, configuration, credentials, and doctor](./setup-configuration-credentials-and-doctor.md) + 6 companion | 331 paths · 2026-10-20 | | `local-web-setup-assistant` | Proposed | Offer a packaged, loopback-only Svelte setup interface over the existing engine with four-language guidance, English CLI help, basic/custom first-run paths, editable question and plan review, source-labelled GitHub facts, assisted CI and Project evidence, role-separated PATs, and truthful itemized outcomes; inspect existing configuration and apply independent, scope-aware runtime adjustments with permission, drift and read-back verification | [Local web setup assistant](./local-web-setup-assistant.md) + 2 companion | 247 paths · 2026-10-21 | | `guided-bot-pat-onboarding` | Proposed | Guide creation of the persistent workflow PAT, verify bot identity and grants, recover explicitly from wrong-account input within the session, and install the approved Actions Secret | [Guided bot PAT onboarding](./guided-bot-pat-onboarding.md) | 39 paths · 2026-10-07 | | `temporary-setup-operator-authorization` | Proposed | Guide creation of the one-run operator PAT through GitHub's official form, verify final setup access, and report user-owned deletion accurately | [Assisted setup PAT creation](./temporary-setup-operator-authorization.md) | 36 paths · 2026-10-18 | @@ -24,7 +24,7 @@ debt or convert unknown historic intent into a design decision. | `managed-issue-lifecycle` | As-built baseline | Convert typed issues into traceable work branches, project state, and lifecycle state | [Managed issue and branch lifecycle](./managed-issue-and-branch-lifecycle.md) | 71 paths · 2026-10-20 | | `comment-automation` | Implemented | Admit only explicit commands or exact mentions, then route them while protecting repository mutations | [Comment automation and authorization](./comment-automation-and-authorization.md) | 79 paths · 2026-10-11 | | `bugbot-analysis-and-autofix` | Implemented | Select one canonical PR, exhaustively analyze its bounded diff partitions, publish stable findings atomically, and apply authorized verified fixes | [Bugbot analysis, finding publication, and autofix](./bugbot-analysis-publication-and-autofix.md) + 2 companion | 115 paths · 2026-10-21 | -| `branch-synchronization` | Implemented | Observe parent drift with one localized status card and transition-only notifications, then safely merge a parent branch into a linked working branch | [Branch synchronization and conflict recovery](./branch-synchronization-and-conflict-recovery.md) + 2 companion | 119 paths · 2026-10-21 | +| `branch-synchronization` | Implemented | Observe parent drift with one localized status card and transition-only notifications, then safely merge a parent branch into a linked working branch | [Branch synchronization and conflict recovery](./branch-synchronization-and-conflict-recovery.md) + 2 companion | 126 paths · 2026-10-21 | | `pull-request-lifecycle` | Implemented | Enrich linked and unlinked pull requests with safe issue linkage, projects, metadata, reviewers, concise descriptions, and distinct workflow evidence | [Pull request lifecycle and enrichment](./pull-request-lifecycle-and-enrichment.md) | 77 paths · 2026-10-20 | | `agent-runtime` | Implemented | Resolve, provision, authenticate, authorize, and execute only the agent roles reachable by a run | [Agent runtime, provider, model, and role routing](./agent-runtime-provider-and-model-routing.md) + 1 companion | 99 paths · 2026-10-17 | | `cli-and-single-actions` | As-built baseline | Expose bounded local commands and workflow-dispatched operations through the shared application core | [CLI and single-action execution](./cli-and-single-action-execution.md) | 44 paths · 2026-10-19 | @@ -104,11 +104,11 @@ debt or convert unknown historic intent into a design decision. - Owner: Copilot maintainers - Last verified: 2026-10-20 -- Specifications: [`specs/setup-configuration-credentials-and-doctor.md`](./setup-configuration-credentials-and-doctor.md) · [`specs/setup-doctor-architecture-hardening.md`](./setup-doctor-architecture-hardening.md) · [`specs/setup-pat-permission-guidance-and-verification.md`](./setup-pat-permission-guidance-and-verification.md) · [`specs/github-runtime-doctor-command.md`](./github-runtime-doctor-command.md) · [`specs/organization-configuration-reuse-and-batch-setup.md`](./organization-configuration-reuse-and-batch-setup.md) · [`specs/setup-runner-profiles-and-installation-parity.md`](./setup-runner-profiles-and-installation-parity.md) +- Specifications: [`specs/setup-configuration-credentials-and-doctor.md`](./setup-configuration-credentials-and-doctor.md) · [`specs/setup-doctor-architecture-hardening.md`](./setup-doctor-architecture-hardening.md) · [`specs/setup-pat-permission-guidance-and-verification.md`](./setup-pat-permission-guidance-and-verification.md) · [`specs/github-runtime-doctor-command.md`](./github-runtime-doctor-command.md) · [`specs/organization-configuration-reuse-and-batch-setup.md`](./organization-configuration-reuse-and-batch-setup.md) · [`specs/setup-runner-profiles-and-installation-parity.md`](./setup-runner-profiles-and-installation-parity.md) · [`specs/copilot-comment-workflow-coordinator.md`](./copilot-comment-workflow-coordinator.md) - Workflows: [`setup/workflows/agent-cli-provisioning.yml`](../setup/workflows/agent-cli-provisioning.yml) · [`setup/workflows/copilot_credential_health.yml`](../setup/workflows/copilot_credential_health.yml) · [`.github/workflows/copilot_issue_comment.yml`](../.github/workflows/copilot_issue_comment.yml) · [`.github/workflows/copilot_pull_request_comment.yml`](../.github/workflows/copilot_pull_request_comment.yml) · [`.github/workflows/agent-cli-provisioning.yml`](../.github/workflows/agent-cli-provisioning.yml) · [`.github/workflows/copilot_credential_health.yml`](../.github/workflows/copilot_credential_health.yml) · [`.github/workflows/copilot_commit.yml`](../.github/workflows/copilot_commit.yml) · [`.github/workflows/copilot_branch_sync.yml`](../.github/workflows/copilot_branch_sync.yml) · [`setup/workflows/copilot_commit.yml`](../setup/workflows/copilot_commit.yml) · [`setup/workflows/copilot_branch_sync.yml`](../setup/workflows/copilot_branch_sync.yml) · [`setup/workflows/copilot_issue_comment.yml`](../setup/workflows/copilot_issue_comment.yml) · [`setup/workflows/copilot_pull_request_comment.yml`](../setup/workflows/copilot_pull_request_comment.yml) - Entrypoints: [`src/cli/commands/setup.ts`](../src/cli/commands/setup.ts) · [`src/cli/commands/doctor.ts`](../src/cli/commands/doctor.ts) · [`src/application/usecases/issue_comment_use_case.ts`](../src/application/usecases/issue_comment_use_case.ts) · [`src/application/usecases/pull_request_review_comment_use_case.ts`](../src/application/usecases/pull_request_review_comment_use_case.ts) -- Core code: [`src/domain/setup.ts`](../src/domain/setup.ts) · [`src/domain/setup_questionnaire.ts`](../src/domain/setup_questionnaire.ts) · [`src/domain/setup_token_permissions.ts`](../src/domain/setup_token_permissions.ts) · [`src/application/ports/setup_terminal_ports.ts`](../src/application/ports/setup_terminal_ports.ts) · [`src/application/ports/setup_wizard_ports.ts`](../src/application/ports/setup_wizard_ports.ts) · [`src/application/ports/branch_tag_ports.ts`](../src/application/ports/branch_tag_ports.ts) · [`src/application/policies/setup_issue_workflow_policy.ts`](../src/application/policies/setup_issue_workflow_policy.ts) · [`src/data/repository/release/repository_version_tags_query_repository.ts`](../src/data/repository/release/repository_version_tags_query_repository.ts) · [`src/application/ports/setup_token_permission_ports.ts`](../src/application/ports/setup_token_permission_ports.ts) · [`src/application/policies/setup_token_permission_evidence_policy.ts`](../src/application/policies/setup_token_permission_evidence_policy.ts) · [`src/application/policies/setup_token_permission_policy.ts`](../src/application/policies/setup_token_permission_policy.ts) · [`src/application/policies/setup_questionnaire_policy.ts`](../src/application/policies/setup_questionnaire_policy.ts) · [`src/application/policies/setup_configuration_plan.ts`](../src/application/policies/setup_configuration_plan.ts) · [`src/application/policies/merge_setup_overrides_policy.ts`](../src/application/policies/merge_setup_overrides_policy.ts) · [`src/application/policies/setup_configuration_storage_policy.ts`](../src/application/policies/setup_configuration_storage_policy.ts) · [`src/application/policies/setup_doctor_message_catalog.ts`](../src/application/policies/setup_doctor_message_catalog.ts) · [`src/application/policies/setup_doctor_report_policy.ts`](../src/application/policies/setup_doctor_report_policy.ts) · [`src/application/policies/setup_journey_policy.ts`](../src/application/policies/setup_journey_policy.ts) · [`src/application/policies/setup_permission_summary_policy.ts`](../src/application/policies/setup_permission_summary_policy.ts) · [`src/application/usecases/setup/setup_wizard_use_case.ts`](../src/application/usecases/setup/setup_wizard_use_case.ts) · [`src/application/usecases/setup/setup_journey_use_case.ts`](../src/application/usecases/setup/setup_journey_use_case.ts) · [`src/application/usecases/setup/setup_session_coordinator.ts`](../src/application/usecases/setup/setup_session_coordinator.ts) · [`src/application/usecases/setup/setup_questionnaire_controller.ts`](../src/application/usecases/setup/setup_questionnaire_controller.ts) · [`src/application/usecases/setup/setup_credentials_use_case.ts`](../src/application/usecases/setup/setup_credentials_use_case.ts) · [`src/application/usecases/setup/setup_token_permissions_use_case.ts`](../src/application/usecases/setup/setup_token_permissions_use_case.ts) · [`src/application/usecases/setup/doctor_use_case.ts`](../src/application/usecases/setup/doctor_use_case.ts) · [`src/application/usecases/setup/merge_queue_readiness_use_case.ts`](../src/application/usecases/setup/merge_queue_readiness_use_case.ts) · [`src/application/usecases/actions/initial_setup_workflow.ts`](../src/application/usecases/actions/initial_setup_workflow.ts) · [`src/application/usecases/actions/setup_resource_provisioning.ts`](../src/application/usecases/actions/setup_resource_provisioning.ts) · [`src/application/ports/message_catalog_ports.ts`](../src/application/ports/message_catalog_ports.ts) · [`src/application/usecases/localization/resolve_message_catalog_use_case.ts`](../src/application/usecases/localization/resolve_message_catalog_use_case.ts) · [`src/application/policies/setup_configuration_validation.ts`](../src/application/policies/setup_configuration_validation.ts) · [`src/infrastructure/setup_workspace_adapter.ts`](../src/infrastructure/setup_workspace_adapter.ts) · [`src/data/repository/repository_variables_repository.ts`](../src/data/repository/repository_variables_repository.ts) · [`src/infrastructure/github/ports/github_repository_variables_protocol.ts`](../src/infrastructure/github/ports/github_repository_variables_protocol.ts) · [`src/infrastructure/setup_remote_credential_health_adapter.ts`](../src/infrastructure/setup_remote_credential_health_adapter.ts) · [`src/infrastructure/setup_credential_validation_adapter.ts`](../src/infrastructure/setup_credential_validation_adapter.ts) · [`src/infrastructure/setup_token_permission_query_adapter.ts`](../src/infrastructure/setup_token_permission_query_adapter.ts) · [`src/infrastructure/setup_permission_actions_probe.ts`](../src/infrastructure/setup_permission_actions_probe.ts) · [`src/infrastructure/setup_permission_issue_probe.ts`](../src/infrastructure/setup_permission_issue_probe.ts) · [`src/infrastructure/setup_permission_issue_cleanup.ts`](../src/infrastructure/setup_permission_issue_cleanup.ts) · [`src/infrastructure/setup_permission_probe_journal.ts`](../src/infrastructure/setup_permission_probe_journal.ts) · [`src/infrastructure/setup_permission_probe_transaction.ts`](../src/infrastructure/setup_permission_probe_transaction.ts) · [`src/infrastructure/setup_permission_resource_probes.ts`](../src/infrastructure/setup_permission_resource_probes.ts) · [`src/infrastructure/setup_projects_probe_page_policy.ts`](../src/infrastructure/setup_projects_probe_page_policy.ts) · [`src/cli/setup_terminal_driver.ts`](../src/cli/setup_terminal_driver.ts) · [`src/cli/setup_question_renderer.ts`](../src/cli/setup_question_renderer.ts) · [`src/cli/setup_journey_presenter.ts`](../src/cli/setup_journey_presenter.ts) · [`src/cli/setup_plan_presenter.ts`](../src/cli/setup_plan_presenter.ts) · [`src/cli/setup_doctor_presenter.ts`](../src/cli/setup_doctor_presenter.ts) · [`src/cli/setup_prompt_rendering.ts`](../src/cli/setup_prompt_rendering.ts) · [`src/cli/setup_credential_prompt_adapter.ts`](../src/cli/setup_credential_prompt_adapter.ts) · [`src/cli/setup_credential_collection.ts`](../src/cli/setup_credential_collection.ts) · [`src/cli/commands/setup_execution.ts`](../src/cli/commands/setup_execution.ts) · [`src/cli/setup_token_permission_presenter.ts`](../src/cli/setup_token_permission_presenter.ts) · [`src/infrastructure/composition/setup_credentials_composition_root.ts`](../src/infrastructure/composition/setup_credentials_composition_root.ts) · [`src/infrastructure/composition/setup_token_permissions_composition_root.ts`](../src/infrastructure/composition/setup_token_permissions_composition_root.ts) · [`src/infrastructure/composition/setup_doctor_composition_root.ts`](../src/infrastructure/composition/setup_doctor_composition_root.ts) · [`scripts/coverage-budgets.json`](../scripts/coverage-budgets.json) · [`scripts/documentation_pat_exception_policy.cjs`](../scripts/documentation_pat_exception_policy.cjs) · [`scripts/validate-documentation-contract.cjs`](../scripts/validate-documentation-contract.cjs) · [`src/infrastructure/http_deadline.ts`](../src/infrastructure/http_deadline.ts) · [`src/infrastructure/setup_permission_denial.ts`](../src/infrastructure/setup_permission_denial.ts) · [`src/infrastructure/setup_permission_read_probe.ts`](../src/infrastructure/setup_permission_read_probe.ts) · [`src/infrastructure/setup_permission_read_evidence.ts`](../src/infrastructure/setup_permission_read_evidence.ts) · [`src/infrastructure/setup_permission_read_shape.ts`](../src/infrastructure/setup_permission_read_shape.ts) · [`src/infrastructure/setup_permission_projects_read.ts`](../src/infrastructure/setup_permission_projects_read.ts) · [`src/infrastructure/setup_permission_projects_access.ts`](../src/infrastructure/setup_permission_projects_access.ts) · [`src/infrastructure/setup_permission_workflow_cleanup.ts`](../src/infrastructure/setup_permission_workflow_cleanup.ts) · [`src/infrastructure/setup_permission_project_cleanup.ts`](../src/infrastructure/setup_permission_project_cleanup.ts) · [`src/infrastructure/setup_permission_probe_http.ts`](../src/infrastructure/setup_permission_probe_http.ts) · [`src/infrastructure/setup_permission_pull_request_probe.ts`](../src/infrastructure/setup_permission_pull_request_probe.ts) · [`src/infrastructure/git_authentication_environment.ts`](../src/infrastructure/git_authentication_environment.ts) · [`src/actions/github_action_input.ts`](../src/actions/github_action_input.ts) · [`src/infrastructure/setup_github_identity_query_adapter.ts`](../src/infrastructure/setup_github_identity_query_adapter.ts) · [`src/infrastructure/github_secret_encryption.ts`](../src/infrastructure/github_secret_encryption.ts) · [`src/infrastructure/setup_permission_organization_owner.ts`](../src/infrastructure/setup_permission_organization_owner.ts) · [`src/data/repository/github/github_actions_resource_inspector.ts`](../src/data/repository/github/github_actions_resource_inspector.ts) · [`src/data/repository/github/github_actions_resource_commands.ts`](../src/data/repository/github/github_actions_resource_commands.ts) · [`src/data/repository/github/github_actions_resource_collection.ts`](../src/data/repository/github/github_actions_resource_collection.ts) · [`src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts`](../src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts) · [`src/cli/setup_workflow_pat_storage_copy.ts`](../src/cli/setup_workflow_pat_storage_copy.ts) · [`src/cli/commands/setup_policy.ts`](../src/cli/commands/setup_policy.ts) · [`src/application/usecases/execution/execution_issue_number_policy.ts`](../src/application/usecases/execution/execution_issue_number_policy.ts) · [`src/application/usecases/execution/setup_execution_workflow.ts`](../src/application/usecases/execution/setup_execution_workflow.ts) · [`src/domain/github_runtime_doctor.ts`](../src/domain/github_runtime_doctor.ts) · [`src/domain/copilot_command.ts`](../src/domain/copilot_command.ts) · [`src/application/usecases/comment_automation_command_workflow.ts`](../src/application/usecases/comment_automation_command_workflow.ts) · [`src/application/policies/copilot_interaction_policy.ts`](../src/application/policies/copilot_interaction_policy.ts) · [`src/application/policies/publication_message_catalog.ts`](../src/application/policies/publication_message_catalog.ts) · [`src/application/ports/github_runtime_doctor_ports.ts`](../src/application/ports/github_runtime_doctor_ports.ts) · [`src/application/policies/github_runtime_doctor_policy.ts`](../src/application/policies/github_runtime_doctor_policy.ts) · [`src/application/policies/doctor_workflow_condition_policy.ts`](../src/application/policies/doctor_workflow_condition_policy.ts) · [`src/application/policies/github_runtime_doctor_presentation_policy.ts`](../src/application/policies/github_runtime_doctor_presentation_policy.ts) · [`src/application/usecases/read_copilot_doctor_workflow.ts`](../src/application/usecases/read_copilot_doctor_workflow.ts) · [`src/data/repository/github/runtime_doctor_repository.ts`](../src/data/repository/github/runtime_doctor_repository.ts) · [`src/infrastructure/composition/github_runtime_doctor_composition_root.ts`](../src/infrastructure/composition/github_runtime_doctor_composition_root.ts) · [`src/application/policies/agent_activity_policy.ts`](../src/application/policies/agent_activity_policy.ts) · [`src/application/policies/doctor_workflow_matrix_policy.ts`](../src/application/policies/doctor_workflow_matrix_policy.ts) · [`src/application/contracts/setup_batch_view.ts`](../src/application/contracts/setup_batch_view.ts) · [`src/application/policies/issue_resource_input_policy.ts`](../src/application/policies/issue_resource_input_policy.ts) · [`src/application/policies/setup_batch_access_policy.ts`](../src/application/policies/setup_batch_access_policy.ts) · [`src/application/policies/setup_batch_policy.ts`](../src/application/policies/setup_batch_policy.ts) · [`src/application/policies/setup_batch_retry_policy.ts`](../src/application/policies/setup_batch_retry_policy.ts) · [`src/application/policies/setup_batch_selection_policy.ts`](../src/application/policies/setup_batch_selection_policy.ts) · [`src/application/policies/setup_batch_view_policy.ts`](../src/application/policies/setup_batch_view_policy.ts) · [`src/application/policies/setup_credential_binding_policy.ts`](../src/application/policies/setup_credential_binding_policy.ts) · [`src/application/policies/setup_organization_import_policy.ts`](../src/application/policies/setup_organization_import_policy.ts) · [`src/application/policies/setup_organization_variable_bindings.ts`](../src/application/policies/setup_organization_variable_bindings.ts) · [`src/application/policies/setup_organization_variable_reuse_policy.ts`](../src/application/policies/setup_organization_variable_reuse_policy.ts) · [`src/application/ports/setup_batch_ports.ts`](../src/application/ports/setup_batch_ports.ts) · [`src/application/usecases/setup/apply_setup_batch_use_case.ts`](../src/application/usecases/setup/apply_setup_batch_use_case.ts) · [`src/application/usecases/setup/configure_setup_batch_target_use_case.ts`](../src/application/usecases/setup/configure_setup_batch_target_use_case.ts) · [`src/application/usecases/setup/prepare_setup_batch_use_case.ts`](../src/application/usecases/setup/prepare_setup_batch_use_case.ts) · [`src/application/usecases/setup/select_setup_batch_targets_use_case.ts`](../src/application/usecases/setup/select_setup_batch_targets_use_case.ts) · [`src/application/usecases/setup/setup_batch_session_use_case.ts`](../src/application/usecases/setup/setup_batch_session_use_case.ts) · [`src/cli/setup_batch_adapter.ts`](../src/cli/setup_batch_adapter.ts) · [`src/cli/setup_source_adapter.ts`](../src/cli/setup_source_adapter.ts) · [`src/domain/setup_batch.ts`](../src/domain/setup_batch.ts) · [`src/domain/setup_credential_health.ts`](../src/domain/setup_credential_health.ts) · [`src/domain/setup_organization_reuse.ts`](../src/domain/setup_organization_reuse.ts) · [`src/infrastructure/composition/setup_batch_composition_root.ts`](../src/infrastructure/composition/setup_batch_composition_root.ts) · [`src/infrastructure/github/ports/github_setup_batch_protocol.ts`](../src/infrastructure/github/ports/github_setup_batch_protocol.ts) · [`src/infrastructure/github/ports/github_trusted_credential_health_protocol.ts`](../src/infrastructure/github/ports/github_trusted_credential_health_protocol.ts) · [`src/infrastructure/setup_batch_github_apply_adapter.ts`](../src/infrastructure/setup_batch_github_apply_adapter.ts) · [`src/infrastructure/setup_batch_github_read_adapter.ts`](../src/infrastructure/setup_batch_github_read_adapter.ts) · [`src/infrastructure/setup_batch_journal_adapter.ts`](../src/infrastructure/setup_batch_journal_adapter.ts) · [`src/infrastructure/setup_batch_workspace_adapter.ts`](../src/infrastructure/setup_batch_workspace_adapter.ts) · [`src/infrastructure/setup_trusted_credential_health_adapter.ts`](../src/infrastructure/setup_trusted_credential_health_adapter.ts) · [`src/application/policies/setup_remote_facts_policy.ts`](../src/application/policies/setup_remote_facts_policy.ts) · [`src/cli/setup_confirmation_adapter.ts`](../src/cli/setup_confirmation_adapter.ts) · [`src/cli/web_setup_adapters.ts`](../src/cli/web_setup_adapters.ts) · [`scripts/validate-agent-documentation.cjs`](../scripts/validate-agent-documentation.cjs) · [`src/utils/setup_workflow_upgrade.ts`](../src/utils/setup_workflow_upgrade.ts) · [`src/domain/setup_runner.ts`](../src/domain/setup_runner.ts) · [`src/application/policies/setup_runner_policy.ts`](../src/application/policies/setup_runner_policy.ts) · [`src/application/policies/setup_runner_question_policy.ts`](../src/application/policies/setup_runner_question_policy.ts) · [`src/application/policies/setup_runner_guidance_policy.ts`](../src/application/policies/setup_runner_guidance_policy.ts) · [`src/application/ports/setup_runner_ports.ts`](../src/application/ports/setup_runner_ports.ts) · [`src/infrastructure/setup_runner_discovery_adapter.ts`](../src/infrastructure/setup_runner_discovery_adapter.ts) · [`src/infrastructure/composition/setup_runner_composition_root.ts`](../src/infrastructure/composition/setup_runner_composition_root.ts) · [`src/utils/setup_installation_review.ts`](../src/utils/setup_installation_review.ts) · [`src/cli/setup_installation_review_presenter.ts`](../src/cli/setup_installation_review_presenter.ts) · [`src/application/policies/setup_runner_installation_summary_policy.ts`](../src/application/policies/setup_runner_installation_summary_policy.ts) · [`src/utils/setup_files.ts`](../src/utils/setup_files.ts) · [`src/domain/specification_catalog_path_policy.cjs`](../src/domain/specification_catalog_path_policy.cjs) · [`src/domain/sdd_prerequisite_policy.cjs`](../src/domain/sdd_prerequisite_policy.cjs) · [`src/application/contracts/setup_documentation.ts`](../src/application/contracts/setup_documentation.ts) · [`src/application/policies/setup_question_documentation_policy.ts`](../src/application/policies/setup_question_documentation_policy.ts) · [`web/src/components/SetupHelp.svelte`](../web/src/components/SetupHelp.svelte) · [`web/src/components/CompletedSetupHelp.svelte`](../web/src/components/CompletedSetupHelp.svelte) · [`src/application/policies/verification_runtime_policy.ts`](../src/application/policies/verification_runtime_policy.ts) · [`src/infrastructure/verification_runtime_manifest.ts`](../src/infrastructure/verification_runtime_manifest.ts) · [`src/infrastructure/verification_runtime_preflight.ts`](../src/infrastructure/verification_runtime_preflight.ts) · [`src/infrastructure/untrusted_command_environment.ts`](../src/infrastructure/untrusted_command_environment.ts) · [`src/application/ports/git_ports.ts`](../src/application/ports/git_ports.ts) · [`src/application/ports/bugbot_git_ports.ts`](../src/application/ports/bugbot_git_ports.ts) · [`src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts`](../src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts) · [`src/application/usecases/steps/commit/bugbot/verify_command_runner.ts`](../src/application/usecases/steps/commit/bugbot/verify_command_runner.ts) · [`src/cli/setup_config_file.ts`](../src/cli/setup_config_file.ts) -- Tests: [`src/data/repository/__tests__/repository_version_tags_query_repository.test.ts`](../src/data/repository/__tests__/repository_version_tags_query_repository.test.ts) · [`src/cli/__tests__/setup_command_options.test.ts`](../src/cli/__tests__/setup_command_options.test.ts) · [`src/data/repository/__tests__/setup_variable_write_failures.test.ts`](../src/data/repository/__tests__/setup_variable_write_failures.test.ts) · [`src/infrastructure/composition/__tests__/initial_setup_composition_root.test.ts`](../src/infrastructure/composition/__tests__/initial_setup_composition_root.test.ts) · [`src/application/policies/__tests__/setup_questionnaire_policy.test.ts`](../src/application/policies/__tests__/setup_questionnaire_policy.test.ts) · [`src/application/policies/__tests__/setup_configuration_policy.test.ts`](../src/application/policies/__tests__/setup_configuration_policy.test.ts) · [`src/application/policies/__tests__/setup_token_permission_policy.test.ts`](../src/application/policies/__tests__/setup_token_permission_policy.test.ts) · [`src/application/policies/__tests__/setup_remote_facts_policy.test.ts`](../src/application/policies/__tests__/setup_remote_facts_policy.test.ts) · [`src/application/policies/__tests__/setup_doctor_message_catalog.test.ts`](../src/application/policies/__tests__/setup_doctor_message_catalog.test.ts) · [`src/application/policies/__tests__/setup_doctor_report_policy.test.ts`](../src/application/policies/__tests__/setup_doctor_report_policy.test.ts) · [`src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts`](../src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts) · [`src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts`](../src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts) · [`src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_token_permissions_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_token_permissions_use_case.test.ts) · [`src/application/usecases/setup/__tests__/doctor_use_case.test.ts`](../src/application/usecases/setup/__tests__/doctor_use_case.test.ts) · [`src/application/usecases/setup/__tests__/merge_queue_readiness_use_case.test.ts`](../src/application/usecases/setup/__tests__/merge_queue_readiness_use_case.test.ts) · [`src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts`](../src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts) · [`src/application/usecases/actions/__tests__/setup_resource_provisioning.test.ts`](../src/application/usecases/actions/__tests__/setup_resource_provisioning.test.ts) · [`src/infrastructure/__tests__/setup_workspace_adapter.test.ts`](../src/infrastructure/__tests__/setup_workspace_adapter.test.ts) · [`src/infrastructure/__tests__/setup_remote_credential_health_adapter.test.ts`](../src/infrastructure/__tests__/setup_remote_credential_health_adapter.test.ts) · [`src/infrastructure/__tests__/setup_token_permission_query_adapter.test.ts`](../src/infrastructure/__tests__/setup_token_permission_query_adapter.test.ts) · [`src/infrastructure/__tests__/setup_permission_resource_probes.test.ts`](../src/infrastructure/__tests__/setup_permission_resource_probes.test.ts) · [`src/infrastructure/__tests__/setup_projects_probe_page_policy.test.ts`](../src/infrastructure/__tests__/setup_projects_probe_page_policy.test.ts) · [`src/infrastructure/composition/__tests__/setup_token_permissions_composition_root.test.ts`](../src/infrastructure/composition/__tests__/setup_token_permissions_composition_root.test.ts) · [`src/data/repository/__tests__/repository_variables_repository.test.ts`](../src/data/repository/__tests__/repository_variables_repository.test.ts) · [`src/cli/__tests__/setup_presenters.test.ts`](../src/cli/__tests__/setup_presenters.test.ts) · [`src/cli/__tests__/setup_journey_presenter.test.ts`](../src/cli/__tests__/setup_journey_presenter.test.ts) · [`src/cli/__tests__/setup_prompt_rendering.test.ts`](../src/cli/__tests__/setup_prompt_rendering.test.ts) · [`src/cli/__tests__/setup_token_permission_presenter.test.ts`](../src/cli/__tests__/setup_token_permission_presenter.test.ts) · [`src/__tests__/cli.test.ts`](../src/__tests__/cli.test.ts) · [`src/cli/__tests__/setup_terminal_driver.test.ts`](../src/cli/__tests__/setup_terminal_driver.test.ts) · [`src/architecture/__tests__/setup_doctor_boundaries.test.ts`](../src/architecture/__tests__/setup_doctor_boundaries.test.ts) · [`src/tooling/__tests__/documentation_pat_exception_policy.test.ts`](../src/tooling/__tests__/documentation_pat_exception_policy.test.ts) · [`src/infrastructure/__tests__/setup_pat_audit.test.ts`](../src/infrastructure/__tests__/setup_pat_audit.test.ts) · [`src/infrastructure/__tests__/setup_permission_projects_access.test.ts`](../src/infrastructure/__tests__/setup_permission_projects_access.test.ts) · [`src/infrastructure/__tests__/setup_credential_validation_adapter.test.ts`](../src/infrastructure/__tests__/setup_credential_validation_adapter.test.ts) · [`src/infrastructure/__tests__/setup_github_identity_query_adapter.test.ts`](../src/infrastructure/__tests__/setup_github_identity_query_adapter.test.ts) · [`src/infrastructure/__tests__/git_commit_adapter.test.ts`](../src/infrastructure/__tests__/git_commit_adapter.test.ts) · [`src/actions/__tests__/github_action_input.test.ts`](../src/actions/__tests__/github_action_input.test.ts) · [`src/infrastructure/__tests__/setup_permission_cleanup_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_cleanup_contract.test.ts) · [`src/infrastructure/__tests__/setup_permission_actions_cleanup_timing.test.ts`](../src/infrastructure/__tests__/setup_permission_actions_cleanup_timing.test.ts) · [`src/infrastructure/__tests__/setup_permission_operator_actions.test.ts`](../src/infrastructure/__tests__/setup_permission_operator_actions.test.ts) · [`src/infrastructure/__tests__/setup_permission_journal_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_journal_contract.test.ts) · [`src/infrastructure/__tests__/setup_permission_audit_transactions.test.ts`](../src/infrastructure/__tests__/setup_permission_audit_transactions.test.ts) · [`src/infrastructure/__tests__/setup_permission_write_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_write_failures.test.ts) · [`src/infrastructure/__tests__/setup_permission_resource_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_resource_failures.test.ts) · [`src/infrastructure/__tests__/setup_permission_boundary_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_boundary_failures.test.ts) · [`src/infrastructure/__tests__/github_secret_encryption.test.ts`](../src/infrastructure/__tests__/github_secret_encryption.test.ts) · [`src/infrastructure/__tests__/setup_permission_organization_owner.test.ts`](../src/infrastructure/__tests__/setup_permission_organization_owner.test.ts) · [`src/infrastructure/__tests__/setup_pat_bootstrap_transactions.test.ts`](../src/infrastructure/__tests__/setup_pat_bootstrap_transactions.test.ts) · [`src/data/repository/__tests__/repository_actions_sdk_contract.integration.test.ts`](../src/data/repository/__tests__/repository_actions_sdk_contract.integration.test.ts) · [`src/data/repository/__tests__/repository_actions_resource_edge_cases.test.ts`](../src/data/repository/__tests__/repository_actions_resource_edge_cases.test.ts) · [`src/data/repository/__tests__/repository_selected_resource_grants.test.ts`](../src/data/repository/__tests__/repository_selected_resource_grants.test.ts) · [`src/infrastructure/__tests__/setup_permission_read_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_read_contract.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts) · [`src/data/repository/__tests__/setup_organization_pat_inventory.test.ts`](../src/data/repository/__tests__/setup_organization_pat_inventory.test.ts) · [`src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts`](../src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts) · [`src/actions/__tests__/local_setup_apply_contract.test.ts`](../src/actions/__tests__/local_setup_apply_contract.test.ts) · [`src/cli/commands/__tests__/setup_policy.test.ts`](../src/cli/commands/__tests__/setup_policy.test.ts) · [`src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts`](../src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts) · [`src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts`](../src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts) · [`src/domain/__tests__/github_runtime_doctor.test.ts`](../src/domain/__tests__/github_runtime_doctor.test.ts) · [`src/domain/__tests__/copilot_command.test.ts`](../src/domain/__tests__/copilot_command.test.ts) · [`src/application/usecases/__tests__/comment_automation_use_case.test.ts`](../src/application/usecases/__tests__/comment_automation_use_case.test.ts) · [`src/application/policies/__tests__/github_runtime_doctor_policy.test.ts`](../src/application/policies/__tests__/github_runtime_doctor_policy.test.ts) · [`src/application/policies/__tests__/doctor_workflow_condition_policy.test.ts`](../src/application/policies/__tests__/doctor_workflow_condition_policy.test.ts) · [`src/application/policies/__tests__/github_runtime_doctor_presentation_policy.test.ts`](../src/application/policies/__tests__/github_runtime_doctor_presentation_policy.test.ts) · [`src/application/usecases/__tests__/read_copilot_doctor_workflow.test.ts`](../src/application/usecases/__tests__/read_copilot_doctor_workflow.test.ts) · [`src/application/usecases/__tests__/runtime_doctor_security_integration.test.ts`](../src/application/usecases/__tests__/runtime_doctor_security_integration.test.ts) · [`src/data/repository/github/__tests__/runtime_doctor_repository.test.ts`](../src/data/repository/github/__tests__/runtime_doctor_repository.test.ts) · [`src/infrastructure/composition/__tests__/github_runtime_doctor_composition_root.test.ts`](../src/infrastructure/composition/__tests__/github_runtime_doctor_composition_root.test.ts) · [`src/application/policies/__tests__/runtime_doctor_agent_activity.test.ts`](../src/application/policies/__tests__/runtime_doctor_agent_activity.test.ts) · [`src/application/policies/__tests__/doctor_workflow_matrix_policy.test.ts`](../src/application/policies/__tests__/doctor_workflow_matrix_policy.test.ts) · [`src/application/policies/__tests__/setup_approval_operator_permissions.test.ts`](../src/application/policies/__tests__/setup_approval_operator_permissions.test.ts) · [`src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts`](../src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts) · [`src/application/policies/__tests__/setup_batch_permission_policy.test.ts`](../src/application/policies/__tests__/setup_batch_permission_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_policy.test.ts`](../src/application/policies/__tests__/setup_batch_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_retry_policy.test.ts`](../src/application/policies/__tests__/setup_batch_retry_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_selection_policy.test.ts`](../src/application/policies/__tests__/setup_batch_selection_policy.test.ts) · [`src/application/policies/__tests__/setup_organization_approval_draft.test.ts`](../src/application/policies/__tests__/setup_organization_approval_draft.test.ts) · [`src/application/policies/__tests__/setup_organization_import_policy.test.ts`](../src/application/policies/__tests__/setup_organization_import_policy.test.ts) · [`src/application/policies/__tests__/setup_organization_import_safety.test.ts`](../src/application/policies/__tests__/setup_organization_import_safety.test.ts) · [`src/application/policies/__tests__/setup_organization_variable_reuse_policy.test.ts`](../src/application/policies/__tests__/setup_organization_variable_reuse_policy.test.ts) · [`src/application/usecases/actions/__tests__/setup_organization_reuse_provisioning.test.ts`](../src/application/usecases/actions/__tests__/setup_organization_reuse_provisioning.test.ts) · [`src/application/usecases/setup/__tests__/apply_setup_batch_use_case.test.ts`](../src/application/usecases/setup/__tests__/apply_setup_batch_use_case.test.ts) · [`src/application/usecases/setup/__tests__/select_setup_batch_targets_use_case.test.ts`](../src/application/usecases/setup/__tests__/select_setup_batch_targets_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_batch_flow.test.ts`](../src/application/usecases/setup/__tests__/setup_batch_flow.test.ts) · [`src/application/usecases/setup/__tests__/setup_organization_import_wizard.test.ts`](../src/application/usecases/setup/__tests__/setup_organization_import_wizard.test.ts) · [`src/application/usecases/setup/__tests__/setup_organization_secret_reuse.test.ts`](../src/application/usecases/setup/__tests__/setup_organization_secret_reuse.test.ts) · [`src/cli/__tests__/setup_source_adapter.test.ts`](../src/cli/__tests__/setup_source_adapter.test.ts) · [`src/cli/__tests__/web_setup_batch_components.test.ts`](../src/cli/__tests__/web_setup_batch_components.test.ts) · [`src/cli/__tests__/web_setup_batch_selection.test.ts`](../src/cli/__tests__/web_setup_batch_selection.test.ts) · [`src/infrastructure/__tests__/setup_batch_github_apply_adapter.test.ts`](../src/infrastructure/__tests__/setup_batch_github_apply_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_github_read_adapter.test.ts`](../src/infrastructure/__tests__/setup_batch_github_read_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_local_adapters.test.ts`](../src/infrastructure/__tests__/setup_batch_local_adapters.test.ts) · [`src/infrastructure/__tests__/setup_reuse_empty_collections.integration.test.ts`](../src/infrastructure/__tests__/setup_reuse_empty_collections.integration.test.ts) · [`src/infrastructure/__tests__/setup_trusted_credential_health_adapter.test.ts`](../src/infrastructure/__tests__/setup_trusted_credential_health_adapter.test.ts) · [`src/infrastructure/__tests__/setup_trusted_health_sdk_contract.integration.test.ts`](../src/infrastructure/__tests__/setup_trusted_health_sdk_contract.integration.test.ts) · [`src/application/policies/__tests__/setup_batch_access_and_view.test.ts`](../src/application/policies/__tests__/setup_batch_access_and_view.test.ts) · [`src/cli/__tests__/setup_batch_adapter.test.ts`](../src/cli/__tests__/setup_batch_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_composition.test.ts`](../src/infrastructure/__tests__/setup_batch_composition.test.ts) · [`src/infrastructure/__tests__/setup_batch_guidance_compatibility.test.ts`](../src/infrastructure/__tests__/setup_batch_guidance_compatibility.test.ts) · [`src/utils/__tests__/setup_workflow_upgrade.test.ts`](../src/utils/__tests__/setup_workflow_upgrade.test.ts) · [`src/cli/__tests__/setup_pat_intent_adapter.test.ts`](../src/cli/__tests__/setup_pat_intent_adapter.test.ts) · [`src/application/usecases/__tests__/push_single_action_contexts.test.ts`](../src/application/usecases/__tests__/push_single_action_contexts.test.ts) · [`src/application/policies/__tests__/setup_runner_policy.test.ts`](../src/application/policies/__tests__/setup_runner_policy.test.ts) · [`src/application/policies/__tests__/setup_runner_question_policy.test.ts`](../src/application/policies/__tests__/setup_runner_question_policy.test.ts) · [`src/infrastructure/__tests__/setup_runner_discovery_adapter.test.ts`](../src/infrastructure/__tests__/setup_runner_discovery_adapter.test.ts) · [`src/utils/__tests__/setup_runner_installation.test.ts`](../src/utils/__tests__/setup_runner_installation.test.ts) · [`src/cli/__tests__/web_setup_runner_components.test.ts`](../src/cli/__tests__/web_setup_runner_components.test.ts) · [`src/application/policies/__tests__/setup_runner_installation_summary_policy.test.ts`](../src/application/policies/__tests__/setup_runner_installation_summary_policy.test.ts) · [`src/application/usecases/setup/__tests__/setup_runner_planning.test.ts`](../src/application/usecases/setup/__tests__/setup_runner_planning.test.ts) · [`src/cli/__tests__/setup_runner_config_file.test.ts`](../src/cli/__tests__/setup_runner_config_file.test.ts) · [`src/infrastructure/__tests__/setup_runner_composition.test.ts`](../src/infrastructure/__tests__/setup_runner_composition.test.ts) · [`src/tooling/__tests__/setup_provisioning_workflow.test.ts`](../src/tooling/__tests__/setup_provisioning_workflow.test.ts) · [`src/infrastructure/__tests__/setup_sdd_prerequisites.test.ts`](../src/infrastructure/__tests__/setup_sdd_prerequisites.test.ts) · [`src/cli/__tests__/setup_documentation_navigation.test.ts`](../src/cli/__tests__/setup_documentation_navigation.test.ts) · [`src/application/policies/__tests__/setup_question_documentation_policy.test.ts`](../src/application/policies/__tests__/setup_question_documentation_policy.test.ts) · [`src/application/policies/__tests__/verification_runtime_policy.test.ts`](../src/application/policies/__tests__/verification_runtime_policy.test.ts) · [`src/infrastructure/__tests__/verification_runtime_preflight.test.ts`](../src/infrastructure/__tests__/verification_runtime_preflight.test.ts) · [`src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts`](../src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts) · [`src/infrastructure/__tests__/untrusted_command_environment.test.ts`](../src/infrastructure/__tests__/untrusted_command_environment.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts) · [`src/tooling/__tests__/verification_runtime_guidance.test.ts`](../src/tooling/__tests__/verification_runtime_guidance.test.ts) · [`src/infrastructure/__tests__/verification_setup_configuration.test.ts`](../src/infrastructure/__tests__/verification_setup_configuration.test.ts) +- Core code: [`src/domain/setup.ts`](../src/domain/setup.ts) · [`src/domain/setup_questionnaire.ts`](../src/domain/setup_questionnaire.ts) · [`src/domain/setup_token_permissions.ts`](../src/domain/setup_token_permissions.ts) · [`src/application/ports/setup_terminal_ports.ts`](../src/application/ports/setup_terminal_ports.ts) · [`src/application/ports/setup_wizard_ports.ts`](../src/application/ports/setup_wizard_ports.ts) · [`src/application/ports/branch_tag_ports.ts`](../src/application/ports/branch_tag_ports.ts) · [`src/application/policies/setup_issue_workflow_policy.ts`](../src/application/policies/setup_issue_workflow_policy.ts) · [`src/data/repository/release/repository_version_tags_query_repository.ts`](../src/data/repository/release/repository_version_tags_query_repository.ts) · [`src/application/ports/setup_token_permission_ports.ts`](../src/application/ports/setup_token_permission_ports.ts) · [`src/application/policies/setup_token_permission_evidence_policy.ts`](../src/application/policies/setup_token_permission_evidence_policy.ts) · [`src/application/policies/setup_token_permission_policy.ts`](../src/application/policies/setup_token_permission_policy.ts) · [`src/application/policies/setup_questionnaire_policy.ts`](../src/application/policies/setup_questionnaire_policy.ts) · [`src/application/policies/setup_configuration_plan.ts`](../src/application/policies/setup_configuration_plan.ts) · [`src/application/policies/merge_setup_overrides_policy.ts`](../src/application/policies/merge_setup_overrides_policy.ts) · [`src/application/policies/setup_configuration_storage_policy.ts`](../src/application/policies/setup_configuration_storage_policy.ts) · [`src/application/policies/setup_doctor_message_catalog.ts`](../src/application/policies/setup_doctor_message_catalog.ts) · [`src/application/policies/setup_doctor_report_policy.ts`](../src/application/policies/setup_doctor_report_policy.ts) · [`src/application/policies/setup_journey_policy.ts`](../src/application/policies/setup_journey_policy.ts) · [`src/application/policies/setup_permission_summary_policy.ts`](../src/application/policies/setup_permission_summary_policy.ts) · [`src/application/usecases/setup/setup_wizard_use_case.ts`](../src/application/usecases/setup/setup_wizard_use_case.ts) · [`src/application/usecases/setup/setup_journey_use_case.ts`](../src/application/usecases/setup/setup_journey_use_case.ts) · [`src/application/usecases/setup/setup_session_coordinator.ts`](../src/application/usecases/setup/setup_session_coordinator.ts) · [`src/application/usecases/setup/setup_questionnaire_controller.ts`](../src/application/usecases/setup/setup_questionnaire_controller.ts) · [`src/application/usecases/setup/setup_credentials_use_case.ts`](../src/application/usecases/setup/setup_credentials_use_case.ts) · [`src/application/usecases/setup/setup_token_permissions_use_case.ts`](../src/application/usecases/setup/setup_token_permissions_use_case.ts) · [`src/application/usecases/setup/doctor_use_case.ts`](../src/application/usecases/setup/doctor_use_case.ts) · [`src/application/usecases/setup/merge_queue_readiness_use_case.ts`](../src/application/usecases/setup/merge_queue_readiness_use_case.ts) · [`src/application/usecases/actions/initial_setup_workflow.ts`](../src/application/usecases/actions/initial_setup_workflow.ts) · [`src/application/usecases/actions/setup_resource_provisioning.ts`](../src/application/usecases/actions/setup_resource_provisioning.ts) · [`src/application/ports/message_catalog_ports.ts`](../src/application/ports/message_catalog_ports.ts) · [`src/application/usecases/localization/resolve_message_catalog_use_case.ts`](../src/application/usecases/localization/resolve_message_catalog_use_case.ts) · [`src/application/policies/setup_configuration_validation.ts`](../src/application/policies/setup_configuration_validation.ts) · [`src/infrastructure/setup_workspace_adapter.ts`](../src/infrastructure/setup_workspace_adapter.ts) · [`src/data/repository/repository_variables_repository.ts`](../src/data/repository/repository_variables_repository.ts) · [`src/infrastructure/github/ports/github_repository_variables_protocol.ts`](../src/infrastructure/github/ports/github_repository_variables_protocol.ts) · [`src/infrastructure/setup_remote_credential_health_adapter.ts`](../src/infrastructure/setup_remote_credential_health_adapter.ts) · [`src/infrastructure/setup_credential_validation_adapter.ts`](../src/infrastructure/setup_credential_validation_adapter.ts) · [`src/infrastructure/setup_token_permission_query_adapter.ts`](../src/infrastructure/setup_token_permission_query_adapter.ts) · [`src/infrastructure/setup_permission_actions_probe.ts`](../src/infrastructure/setup_permission_actions_probe.ts) · [`src/infrastructure/setup_permission_issue_probe.ts`](../src/infrastructure/setup_permission_issue_probe.ts) · [`src/infrastructure/setup_permission_issue_cleanup.ts`](../src/infrastructure/setup_permission_issue_cleanup.ts) · [`src/infrastructure/setup_permission_probe_journal.ts`](../src/infrastructure/setup_permission_probe_journal.ts) · [`src/infrastructure/setup_permission_probe_transaction.ts`](../src/infrastructure/setup_permission_probe_transaction.ts) · [`src/infrastructure/setup_permission_resource_probes.ts`](../src/infrastructure/setup_permission_resource_probes.ts) · [`src/infrastructure/setup_projects_probe_page_policy.ts`](../src/infrastructure/setup_projects_probe_page_policy.ts) · [`src/cli/setup_terminal_driver.ts`](../src/cli/setup_terminal_driver.ts) · [`src/cli/setup_question_renderer.ts`](../src/cli/setup_question_renderer.ts) · [`src/cli/setup_journey_presenter.ts`](../src/cli/setup_journey_presenter.ts) · [`src/cli/setup_plan_presenter.ts`](../src/cli/setup_plan_presenter.ts) · [`src/cli/setup_doctor_presenter.ts`](../src/cli/setup_doctor_presenter.ts) · [`src/cli/setup_prompt_rendering.ts`](../src/cli/setup_prompt_rendering.ts) · [`src/cli/setup_credential_prompt_adapter.ts`](../src/cli/setup_credential_prompt_adapter.ts) · [`src/cli/setup_credential_collection.ts`](../src/cli/setup_credential_collection.ts) · [`src/cli/commands/setup_execution.ts`](../src/cli/commands/setup_execution.ts) · [`src/cli/setup_token_permission_presenter.ts`](../src/cli/setup_token_permission_presenter.ts) · [`src/infrastructure/composition/setup_credentials_composition_root.ts`](../src/infrastructure/composition/setup_credentials_composition_root.ts) · [`src/infrastructure/composition/setup_token_permissions_composition_root.ts`](../src/infrastructure/composition/setup_token_permissions_composition_root.ts) · [`src/infrastructure/composition/setup_doctor_composition_root.ts`](../src/infrastructure/composition/setup_doctor_composition_root.ts) · [`scripts/coverage-budgets.json`](../scripts/coverage-budgets.json) · [`scripts/documentation_pat_exception_policy.cjs`](../scripts/documentation_pat_exception_policy.cjs) · [`scripts/validate-documentation-contract.cjs`](../scripts/validate-documentation-contract.cjs) · [`src/infrastructure/http_deadline.ts`](../src/infrastructure/http_deadline.ts) · [`src/infrastructure/setup_permission_denial.ts`](../src/infrastructure/setup_permission_denial.ts) · [`src/infrastructure/setup_permission_read_probe.ts`](../src/infrastructure/setup_permission_read_probe.ts) · [`src/infrastructure/setup_permission_read_evidence.ts`](../src/infrastructure/setup_permission_read_evidence.ts) · [`src/infrastructure/setup_permission_read_shape.ts`](../src/infrastructure/setup_permission_read_shape.ts) · [`src/infrastructure/setup_permission_projects_read.ts`](../src/infrastructure/setup_permission_projects_read.ts) · [`src/infrastructure/setup_permission_projects_access.ts`](../src/infrastructure/setup_permission_projects_access.ts) · [`src/infrastructure/setup_permission_workflow_cleanup.ts`](../src/infrastructure/setup_permission_workflow_cleanup.ts) · [`src/infrastructure/setup_permission_project_cleanup.ts`](../src/infrastructure/setup_permission_project_cleanup.ts) · [`src/infrastructure/setup_permission_probe_http.ts`](../src/infrastructure/setup_permission_probe_http.ts) · [`src/infrastructure/setup_permission_pull_request_probe.ts`](../src/infrastructure/setup_permission_pull_request_probe.ts) · [`src/infrastructure/git_authentication_environment.ts`](../src/infrastructure/git_authentication_environment.ts) · [`src/actions/github_action_input.ts`](../src/actions/github_action_input.ts) · [`src/infrastructure/setup_github_identity_query_adapter.ts`](../src/infrastructure/setup_github_identity_query_adapter.ts) · [`src/infrastructure/github_secret_encryption.ts`](../src/infrastructure/github_secret_encryption.ts) · [`src/infrastructure/setup_permission_organization_owner.ts`](../src/infrastructure/setup_permission_organization_owner.ts) · [`src/data/repository/github/github_actions_resource_inspector.ts`](../src/data/repository/github/github_actions_resource_inspector.ts) · [`src/data/repository/github/github_actions_resource_commands.ts`](../src/data/repository/github/github_actions_resource_commands.ts) · [`src/data/repository/github/github_actions_resource_collection.ts`](../src/data/repository/github/github_actions_resource_collection.ts) · [`src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts`](../src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts) · [`src/cli/setup_workflow_pat_storage_copy.ts`](../src/cli/setup_workflow_pat_storage_copy.ts) · [`src/cli/commands/setup_policy.ts`](../src/cli/commands/setup_policy.ts) · [`src/application/usecases/execution/execution_issue_number_policy.ts`](../src/application/usecases/execution/execution_issue_number_policy.ts) · [`src/application/usecases/execution/setup_execution_workflow.ts`](../src/application/usecases/execution/setup_execution_workflow.ts) · [`src/domain/github_runtime_doctor.ts`](../src/domain/github_runtime_doctor.ts) · [`src/domain/copilot_command.ts`](../src/domain/copilot_command.ts) · [`src/application/usecases/comment_automation_command_workflow.ts`](../src/application/usecases/comment_automation_command_workflow.ts) · [`src/application/policies/copilot_interaction_policy.ts`](../src/application/policies/copilot_interaction_policy.ts) · [`src/application/policies/publication_message_catalog.ts`](../src/application/policies/publication_message_catalog.ts) · [`src/application/ports/github_runtime_doctor_ports.ts`](../src/application/ports/github_runtime_doctor_ports.ts) · [`src/application/policies/github_runtime_doctor_policy.ts`](../src/application/policies/github_runtime_doctor_policy.ts) · [`src/application/policies/doctor_workflow_condition_policy.ts`](../src/application/policies/doctor_workflow_condition_policy.ts) · [`src/application/policies/github_runtime_doctor_presentation_policy.ts`](../src/application/policies/github_runtime_doctor_presentation_policy.ts) · [`src/application/usecases/read_copilot_doctor_workflow.ts`](../src/application/usecases/read_copilot_doctor_workflow.ts) · [`src/data/repository/github/runtime_doctor_repository.ts`](../src/data/repository/github/runtime_doctor_repository.ts) · [`src/infrastructure/composition/github_runtime_doctor_composition_root.ts`](../src/infrastructure/composition/github_runtime_doctor_composition_root.ts) · [`src/application/policies/agent_activity_policy.ts`](../src/application/policies/agent_activity_policy.ts) · [`src/application/policies/doctor_workflow_matrix_policy.ts`](../src/application/policies/doctor_workflow_matrix_policy.ts) · [`src/application/contracts/setup_batch_view.ts`](../src/application/contracts/setup_batch_view.ts) · [`src/application/policies/issue_resource_input_policy.ts`](../src/application/policies/issue_resource_input_policy.ts) · [`src/application/policies/setup_batch_access_policy.ts`](../src/application/policies/setup_batch_access_policy.ts) · [`src/application/policies/setup_batch_policy.ts`](../src/application/policies/setup_batch_policy.ts) · [`src/application/policies/setup_batch_retry_policy.ts`](../src/application/policies/setup_batch_retry_policy.ts) · [`src/application/policies/setup_batch_selection_policy.ts`](../src/application/policies/setup_batch_selection_policy.ts) · [`src/application/policies/setup_batch_view_policy.ts`](../src/application/policies/setup_batch_view_policy.ts) · [`src/application/policies/setup_credential_binding_policy.ts`](../src/application/policies/setup_credential_binding_policy.ts) · [`src/application/policies/setup_organization_import_policy.ts`](../src/application/policies/setup_organization_import_policy.ts) · [`src/application/policies/setup_organization_variable_bindings.ts`](../src/application/policies/setup_organization_variable_bindings.ts) · [`src/application/policies/setup_organization_variable_reuse_policy.ts`](../src/application/policies/setup_organization_variable_reuse_policy.ts) · [`src/application/ports/setup_batch_ports.ts`](../src/application/ports/setup_batch_ports.ts) · [`src/application/usecases/setup/apply_setup_batch_use_case.ts`](../src/application/usecases/setup/apply_setup_batch_use_case.ts) · [`src/application/usecases/setup/configure_setup_batch_target_use_case.ts`](../src/application/usecases/setup/configure_setup_batch_target_use_case.ts) · [`src/application/usecases/setup/prepare_setup_batch_use_case.ts`](../src/application/usecases/setup/prepare_setup_batch_use_case.ts) · [`src/application/usecases/setup/select_setup_batch_targets_use_case.ts`](../src/application/usecases/setup/select_setup_batch_targets_use_case.ts) · [`src/application/usecases/setup/setup_batch_session_use_case.ts`](../src/application/usecases/setup/setup_batch_session_use_case.ts) · [`src/cli/setup_batch_adapter.ts`](../src/cli/setup_batch_adapter.ts) · [`src/cli/setup_source_adapter.ts`](../src/cli/setup_source_adapter.ts) · [`src/domain/setup_batch.ts`](../src/domain/setup_batch.ts) · [`src/domain/setup_credential_health.ts`](../src/domain/setup_credential_health.ts) · [`src/domain/setup_organization_reuse.ts`](../src/domain/setup_organization_reuse.ts) · [`src/infrastructure/composition/setup_batch_composition_root.ts`](../src/infrastructure/composition/setup_batch_composition_root.ts) · [`src/infrastructure/github/ports/github_setup_batch_protocol.ts`](../src/infrastructure/github/ports/github_setup_batch_protocol.ts) · [`src/infrastructure/github/ports/github_trusted_credential_health_protocol.ts`](../src/infrastructure/github/ports/github_trusted_credential_health_protocol.ts) · [`src/infrastructure/setup_batch_github_apply_adapter.ts`](../src/infrastructure/setup_batch_github_apply_adapter.ts) · [`src/infrastructure/setup_batch_github_read_adapter.ts`](../src/infrastructure/setup_batch_github_read_adapter.ts) · [`src/infrastructure/setup_batch_journal_adapter.ts`](../src/infrastructure/setup_batch_journal_adapter.ts) · [`src/infrastructure/setup_batch_workspace_adapter.ts`](../src/infrastructure/setup_batch_workspace_adapter.ts) · [`src/infrastructure/setup_trusted_credential_health_adapter.ts`](../src/infrastructure/setup_trusted_credential_health_adapter.ts) · [`src/application/policies/setup_remote_facts_policy.ts`](../src/application/policies/setup_remote_facts_policy.ts) · [`src/cli/setup_confirmation_adapter.ts`](../src/cli/setup_confirmation_adapter.ts) · [`src/cli/web_setup_adapters.ts`](../src/cli/web_setup_adapters.ts) · [`scripts/validate-agent-documentation.cjs`](../scripts/validate-agent-documentation.cjs) · [`src/utils/setup_workflow_upgrade.ts`](../src/utils/setup_workflow_upgrade.ts) · [`src/domain/setup_runner.ts`](../src/domain/setup_runner.ts) · [`src/application/policies/setup_runner_policy.ts`](../src/application/policies/setup_runner_policy.ts) · [`src/application/policies/setup_runner_question_policy.ts`](../src/application/policies/setup_runner_question_policy.ts) · [`src/application/policies/setup_runner_guidance_policy.ts`](../src/application/policies/setup_runner_guidance_policy.ts) · [`src/application/ports/setup_runner_ports.ts`](../src/application/ports/setup_runner_ports.ts) · [`src/infrastructure/setup_runner_discovery_adapter.ts`](../src/infrastructure/setup_runner_discovery_adapter.ts) · [`src/infrastructure/composition/setup_runner_composition_root.ts`](../src/infrastructure/composition/setup_runner_composition_root.ts) · [`src/utils/setup_installation_review.ts`](../src/utils/setup_installation_review.ts) · [`src/cli/setup_installation_review_presenter.ts`](../src/cli/setup_installation_review_presenter.ts) · [`src/application/policies/setup_runner_installation_summary_policy.ts`](../src/application/policies/setup_runner_installation_summary_policy.ts) · [`src/utils/setup_files.ts`](../src/utils/setup_files.ts) · [`src/domain/specification_catalog_path_policy.cjs`](../src/domain/specification_catalog_path_policy.cjs) · [`src/domain/sdd_prerequisite_policy.cjs`](../src/domain/sdd_prerequisite_policy.cjs) · [`src/application/contracts/setup_documentation.ts`](../src/application/contracts/setup_documentation.ts) · [`src/application/policies/setup_question_documentation_policy.ts`](../src/application/policies/setup_question_documentation_policy.ts) · [`web/src/components/SetupHelp.svelte`](../web/src/components/SetupHelp.svelte) · [`web/src/components/CompletedSetupHelp.svelte`](../web/src/components/CompletedSetupHelp.svelte) · [`src/application/policies/verification_runtime_policy.ts`](../src/application/policies/verification_runtime_policy.ts) · [`src/infrastructure/verification_runtime_manifest.ts`](../src/infrastructure/verification_runtime_manifest.ts) · [`src/infrastructure/verification_runtime_preflight.ts`](../src/infrastructure/verification_runtime_preflight.ts) · [`src/infrastructure/untrusted_command_environment.ts`](../src/infrastructure/untrusted_command_environment.ts) · [`src/application/ports/git_ports.ts`](../src/application/ports/git_ports.ts) · [`src/application/ports/bugbot_git_ports.ts`](../src/application/ports/bugbot_git_ports.ts) · [`src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts`](../src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts) · [`src/application/usecases/steps/commit/bugbot/verify_command_runner.ts`](../src/application/usecases/steps/commit/bugbot/verify_command_runner.ts) · [`src/cli/setup_config_file.ts`](../src/cli/setup_config_file.ts) · [`src/domain/copilot_comment_workflow.ts`](../src/domain/copilot_comment_workflow.ts) · [`src/infrastructure/copilot_comment_inputs.json`](../src/infrastructure/copilot_comment_inputs.json) +- Tests: [`src/data/repository/__tests__/repository_version_tags_query_repository.test.ts`](../src/data/repository/__tests__/repository_version_tags_query_repository.test.ts) · [`src/cli/__tests__/setup_command_options.test.ts`](../src/cli/__tests__/setup_command_options.test.ts) · [`src/data/repository/__tests__/setup_variable_write_failures.test.ts`](../src/data/repository/__tests__/setup_variable_write_failures.test.ts) · [`src/infrastructure/composition/__tests__/initial_setup_composition_root.test.ts`](../src/infrastructure/composition/__tests__/initial_setup_composition_root.test.ts) · [`src/application/policies/__tests__/setup_questionnaire_policy.test.ts`](../src/application/policies/__tests__/setup_questionnaire_policy.test.ts) · [`src/application/policies/__tests__/setup_configuration_policy.test.ts`](../src/application/policies/__tests__/setup_configuration_policy.test.ts) · [`src/application/policies/__tests__/setup_token_permission_policy.test.ts`](../src/application/policies/__tests__/setup_token_permission_policy.test.ts) · [`src/application/policies/__tests__/setup_remote_facts_policy.test.ts`](../src/application/policies/__tests__/setup_remote_facts_policy.test.ts) · [`src/application/policies/__tests__/setup_doctor_message_catalog.test.ts`](../src/application/policies/__tests__/setup_doctor_message_catalog.test.ts) · [`src/application/policies/__tests__/setup_doctor_report_policy.test.ts`](../src/application/policies/__tests__/setup_doctor_report_policy.test.ts) · [`src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts`](../src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts) · [`src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts`](../src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts) · [`src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_token_permissions_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_token_permissions_use_case.test.ts) · [`src/application/usecases/setup/__tests__/doctor_use_case.test.ts`](../src/application/usecases/setup/__tests__/doctor_use_case.test.ts) · [`src/application/usecases/setup/__tests__/merge_queue_readiness_use_case.test.ts`](../src/application/usecases/setup/__tests__/merge_queue_readiness_use_case.test.ts) · [`src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts`](../src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts) · [`src/application/usecases/actions/__tests__/setup_resource_provisioning.test.ts`](../src/application/usecases/actions/__tests__/setup_resource_provisioning.test.ts) · [`src/infrastructure/__tests__/setup_workspace_adapter.test.ts`](../src/infrastructure/__tests__/setup_workspace_adapter.test.ts) · [`src/infrastructure/__tests__/setup_remote_credential_health_adapter.test.ts`](../src/infrastructure/__tests__/setup_remote_credential_health_adapter.test.ts) · [`src/infrastructure/__tests__/setup_token_permission_query_adapter.test.ts`](../src/infrastructure/__tests__/setup_token_permission_query_adapter.test.ts) · [`src/infrastructure/__tests__/setup_permission_resource_probes.test.ts`](../src/infrastructure/__tests__/setup_permission_resource_probes.test.ts) · [`src/infrastructure/__tests__/setup_projects_probe_page_policy.test.ts`](../src/infrastructure/__tests__/setup_projects_probe_page_policy.test.ts) · [`src/infrastructure/composition/__tests__/setup_token_permissions_composition_root.test.ts`](../src/infrastructure/composition/__tests__/setup_token_permissions_composition_root.test.ts) · [`src/data/repository/__tests__/repository_variables_repository.test.ts`](../src/data/repository/__tests__/repository_variables_repository.test.ts) · [`src/cli/__tests__/setup_presenters.test.ts`](../src/cli/__tests__/setup_presenters.test.ts) · [`src/cli/__tests__/setup_journey_presenter.test.ts`](../src/cli/__tests__/setup_journey_presenter.test.ts) · [`src/cli/__tests__/setup_prompt_rendering.test.ts`](../src/cli/__tests__/setup_prompt_rendering.test.ts) · [`src/cli/__tests__/setup_token_permission_presenter.test.ts`](../src/cli/__tests__/setup_token_permission_presenter.test.ts) · [`src/__tests__/cli.test.ts`](../src/__tests__/cli.test.ts) · [`src/cli/__tests__/setup_terminal_driver.test.ts`](../src/cli/__tests__/setup_terminal_driver.test.ts) · [`src/architecture/__tests__/setup_doctor_boundaries.test.ts`](../src/architecture/__tests__/setup_doctor_boundaries.test.ts) · [`src/tooling/__tests__/documentation_pat_exception_policy.test.ts`](../src/tooling/__tests__/documentation_pat_exception_policy.test.ts) · [`src/infrastructure/__tests__/setup_pat_audit.test.ts`](../src/infrastructure/__tests__/setup_pat_audit.test.ts) · [`src/infrastructure/__tests__/setup_permission_projects_access.test.ts`](../src/infrastructure/__tests__/setup_permission_projects_access.test.ts) · [`src/infrastructure/__tests__/setup_credential_validation_adapter.test.ts`](../src/infrastructure/__tests__/setup_credential_validation_adapter.test.ts) · [`src/infrastructure/__tests__/setup_github_identity_query_adapter.test.ts`](../src/infrastructure/__tests__/setup_github_identity_query_adapter.test.ts) · [`src/infrastructure/__tests__/git_commit_adapter.test.ts`](../src/infrastructure/__tests__/git_commit_adapter.test.ts) · [`src/actions/__tests__/github_action_input.test.ts`](../src/actions/__tests__/github_action_input.test.ts) · [`src/infrastructure/__tests__/setup_permission_cleanup_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_cleanup_contract.test.ts) · [`src/infrastructure/__tests__/setup_permission_actions_cleanup_timing.test.ts`](../src/infrastructure/__tests__/setup_permission_actions_cleanup_timing.test.ts) · [`src/infrastructure/__tests__/setup_permission_operator_actions.test.ts`](../src/infrastructure/__tests__/setup_permission_operator_actions.test.ts) · [`src/infrastructure/__tests__/setup_permission_journal_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_journal_contract.test.ts) · [`src/infrastructure/__tests__/setup_permission_audit_transactions.test.ts`](../src/infrastructure/__tests__/setup_permission_audit_transactions.test.ts) · [`src/infrastructure/__tests__/setup_permission_write_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_write_failures.test.ts) · [`src/infrastructure/__tests__/setup_permission_resource_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_resource_failures.test.ts) · [`src/infrastructure/__tests__/setup_permission_boundary_failures.test.ts`](../src/infrastructure/__tests__/setup_permission_boundary_failures.test.ts) · [`src/infrastructure/__tests__/github_secret_encryption.test.ts`](../src/infrastructure/__tests__/github_secret_encryption.test.ts) · [`src/infrastructure/__tests__/setup_permission_organization_owner.test.ts`](../src/infrastructure/__tests__/setup_permission_organization_owner.test.ts) · [`src/infrastructure/__tests__/setup_pat_bootstrap_transactions.test.ts`](../src/infrastructure/__tests__/setup_pat_bootstrap_transactions.test.ts) · [`src/data/repository/__tests__/repository_actions_sdk_contract.integration.test.ts`](../src/data/repository/__tests__/repository_actions_sdk_contract.integration.test.ts) · [`src/data/repository/__tests__/repository_actions_resource_edge_cases.test.ts`](../src/data/repository/__tests__/repository_actions_resource_edge_cases.test.ts) · [`src/data/repository/__tests__/repository_selected_resource_grants.test.ts`](../src/data/repository/__tests__/repository_selected_resource_grants.test.ts) · [`src/infrastructure/__tests__/setup_permission_read_contract.test.ts`](../src/infrastructure/__tests__/setup_permission_read_contract.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts) · [`src/data/repository/__tests__/setup_organization_pat_inventory.test.ts`](../src/data/repository/__tests__/setup_organization_pat_inventory.test.ts) · [`src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts`](../src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts) · [`src/actions/__tests__/local_setup_apply_contract.test.ts`](../src/actions/__tests__/local_setup_apply_contract.test.ts) · [`src/cli/commands/__tests__/setup_policy.test.ts`](../src/cli/commands/__tests__/setup_policy.test.ts) · [`src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts`](../src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts) · [`src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts`](../src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts) · [`src/domain/__tests__/github_runtime_doctor.test.ts`](../src/domain/__tests__/github_runtime_doctor.test.ts) · [`src/domain/__tests__/copilot_command.test.ts`](../src/domain/__tests__/copilot_command.test.ts) · [`src/application/usecases/__tests__/comment_automation_use_case.test.ts`](../src/application/usecases/__tests__/comment_automation_use_case.test.ts) · [`src/application/policies/__tests__/github_runtime_doctor_policy.test.ts`](../src/application/policies/__tests__/github_runtime_doctor_policy.test.ts) · [`src/application/policies/__tests__/doctor_workflow_condition_policy.test.ts`](../src/application/policies/__tests__/doctor_workflow_condition_policy.test.ts) · [`src/application/policies/__tests__/github_runtime_doctor_presentation_policy.test.ts`](../src/application/policies/__tests__/github_runtime_doctor_presentation_policy.test.ts) · [`src/application/usecases/__tests__/read_copilot_doctor_workflow.test.ts`](../src/application/usecases/__tests__/read_copilot_doctor_workflow.test.ts) · [`src/application/usecases/__tests__/runtime_doctor_security_integration.test.ts`](../src/application/usecases/__tests__/runtime_doctor_security_integration.test.ts) · [`src/data/repository/github/__tests__/runtime_doctor_repository.test.ts`](../src/data/repository/github/__tests__/runtime_doctor_repository.test.ts) · [`src/infrastructure/composition/__tests__/github_runtime_doctor_composition_root.test.ts`](../src/infrastructure/composition/__tests__/github_runtime_doctor_composition_root.test.ts) · [`src/application/policies/__tests__/runtime_doctor_agent_activity.test.ts`](../src/application/policies/__tests__/runtime_doctor_agent_activity.test.ts) · [`src/application/policies/__tests__/doctor_workflow_matrix_policy.test.ts`](../src/application/policies/__tests__/doctor_workflow_matrix_policy.test.ts) · [`src/application/policies/__tests__/setup_approval_operator_permissions.test.ts`](../src/application/policies/__tests__/setup_approval_operator_permissions.test.ts) · [`src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts`](../src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts) · [`src/application/policies/__tests__/setup_batch_permission_policy.test.ts`](../src/application/policies/__tests__/setup_batch_permission_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_policy.test.ts`](../src/application/policies/__tests__/setup_batch_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_retry_policy.test.ts`](../src/application/policies/__tests__/setup_batch_retry_policy.test.ts) · [`src/application/policies/__tests__/setup_batch_selection_policy.test.ts`](../src/application/policies/__tests__/setup_batch_selection_policy.test.ts) · [`src/application/policies/__tests__/setup_organization_approval_draft.test.ts`](../src/application/policies/__tests__/setup_organization_approval_draft.test.ts) · [`src/application/policies/__tests__/setup_organization_import_policy.test.ts`](../src/application/policies/__tests__/setup_organization_import_policy.test.ts) · [`src/application/policies/__tests__/setup_organization_import_safety.test.ts`](../src/application/policies/__tests__/setup_organization_import_safety.test.ts) · [`src/application/policies/__tests__/setup_organization_variable_reuse_policy.test.ts`](../src/application/policies/__tests__/setup_organization_variable_reuse_policy.test.ts) · [`src/application/usecases/actions/__tests__/setup_organization_reuse_provisioning.test.ts`](../src/application/usecases/actions/__tests__/setup_organization_reuse_provisioning.test.ts) · [`src/application/usecases/setup/__tests__/apply_setup_batch_use_case.test.ts`](../src/application/usecases/setup/__tests__/apply_setup_batch_use_case.test.ts) · [`src/application/usecases/setup/__tests__/select_setup_batch_targets_use_case.test.ts`](../src/application/usecases/setup/__tests__/select_setup_batch_targets_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_batch_flow.test.ts`](../src/application/usecases/setup/__tests__/setup_batch_flow.test.ts) · [`src/application/usecases/setup/__tests__/setup_organization_import_wizard.test.ts`](../src/application/usecases/setup/__tests__/setup_organization_import_wizard.test.ts) · [`src/application/usecases/setup/__tests__/setup_organization_secret_reuse.test.ts`](../src/application/usecases/setup/__tests__/setup_organization_secret_reuse.test.ts) · [`src/cli/__tests__/setup_source_adapter.test.ts`](../src/cli/__tests__/setup_source_adapter.test.ts) · [`src/cli/__tests__/web_setup_batch_components.test.ts`](../src/cli/__tests__/web_setup_batch_components.test.ts) · [`src/cli/__tests__/web_setup_batch_selection.test.ts`](../src/cli/__tests__/web_setup_batch_selection.test.ts) · [`src/infrastructure/__tests__/setup_batch_github_apply_adapter.test.ts`](../src/infrastructure/__tests__/setup_batch_github_apply_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_github_read_adapter.test.ts`](../src/infrastructure/__tests__/setup_batch_github_read_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_local_adapters.test.ts`](../src/infrastructure/__tests__/setup_batch_local_adapters.test.ts) · [`src/infrastructure/__tests__/setup_reuse_empty_collections.integration.test.ts`](../src/infrastructure/__tests__/setup_reuse_empty_collections.integration.test.ts) · [`src/infrastructure/__tests__/setup_trusted_credential_health_adapter.test.ts`](../src/infrastructure/__tests__/setup_trusted_credential_health_adapter.test.ts) · [`src/infrastructure/__tests__/setup_trusted_health_sdk_contract.integration.test.ts`](../src/infrastructure/__tests__/setup_trusted_health_sdk_contract.integration.test.ts) · [`src/application/policies/__tests__/setup_batch_access_and_view.test.ts`](../src/application/policies/__tests__/setup_batch_access_and_view.test.ts) · [`src/cli/__tests__/setup_batch_adapter.test.ts`](../src/cli/__tests__/setup_batch_adapter.test.ts) · [`src/infrastructure/__tests__/setup_batch_composition.test.ts`](../src/infrastructure/__tests__/setup_batch_composition.test.ts) · [`src/infrastructure/__tests__/setup_batch_guidance_compatibility.test.ts`](../src/infrastructure/__tests__/setup_batch_guidance_compatibility.test.ts) · [`src/utils/__tests__/setup_workflow_upgrade.test.ts`](../src/utils/__tests__/setup_workflow_upgrade.test.ts) · [`src/cli/__tests__/setup_pat_intent_adapter.test.ts`](../src/cli/__tests__/setup_pat_intent_adapter.test.ts) · [`src/application/usecases/__tests__/push_single_action_contexts.test.ts`](../src/application/usecases/__tests__/push_single_action_contexts.test.ts) · [`src/application/policies/__tests__/setup_runner_policy.test.ts`](../src/application/policies/__tests__/setup_runner_policy.test.ts) · [`src/application/policies/__tests__/setup_runner_question_policy.test.ts`](../src/application/policies/__tests__/setup_runner_question_policy.test.ts) · [`src/infrastructure/__tests__/setup_runner_discovery_adapter.test.ts`](../src/infrastructure/__tests__/setup_runner_discovery_adapter.test.ts) · [`src/utils/__tests__/setup_runner_installation.test.ts`](../src/utils/__tests__/setup_runner_installation.test.ts) · [`src/cli/__tests__/web_setup_runner_components.test.ts`](../src/cli/__tests__/web_setup_runner_components.test.ts) · [`src/application/policies/__tests__/setup_runner_installation_summary_policy.test.ts`](../src/application/policies/__tests__/setup_runner_installation_summary_policy.test.ts) · [`src/application/usecases/setup/__tests__/setup_runner_planning.test.ts`](../src/application/usecases/setup/__tests__/setup_runner_planning.test.ts) · [`src/cli/__tests__/setup_runner_config_file.test.ts`](../src/cli/__tests__/setup_runner_config_file.test.ts) · [`src/infrastructure/__tests__/setup_runner_composition.test.ts`](../src/infrastructure/__tests__/setup_runner_composition.test.ts) · [`src/tooling/__tests__/setup_provisioning_workflow.test.ts`](../src/tooling/__tests__/setup_provisioning_workflow.test.ts) · [`src/infrastructure/__tests__/setup_sdd_prerequisites.test.ts`](../src/infrastructure/__tests__/setup_sdd_prerequisites.test.ts) · [`src/cli/__tests__/setup_documentation_navigation.test.ts`](../src/cli/__tests__/setup_documentation_navigation.test.ts) · [`src/application/policies/__tests__/setup_question_documentation_policy.test.ts`](../src/application/policies/__tests__/setup_question_documentation_policy.test.ts) · [`src/application/policies/__tests__/verification_runtime_policy.test.ts`](../src/application/policies/__tests__/verification_runtime_policy.test.ts) · [`src/infrastructure/__tests__/verification_runtime_preflight.test.ts`](../src/infrastructure/__tests__/verification_runtime_preflight.test.ts) · [`src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts`](../src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts) · [`src/infrastructure/__tests__/untrusted_command_environment.test.ts`](../src/infrastructure/__tests__/untrusted_command_environment.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts) · [`src/tooling/__tests__/verification_runtime_guidance.test.ts`](../src/tooling/__tests__/verification_runtime_guidance.test.ts) · [`src/infrastructure/__tests__/verification_setup_configuration.test.ts`](../src/infrastructure/__tests__/verification_setup_configuration.test.ts) · [`src/domain/__tests__/copilot_comment_workflow.test.ts`](../src/domain/__tests__/copilot_comment_workflow.test.ts) - User documentation: [`README.md`](../README.md) · [`docs/how-to-use.mdx`](../docs/how-to-use.mdx) · [`docs/configuration.mdx`](../docs/configuration.mdx) · [`docs/configuration-checklist.mdx`](../docs/configuration-checklist.mdx) · [`docs/authentication.mdx`](../docs/authentication.mdx) · [`docs/development/architecture.mdx`](../docs/development/architecture.mdx) · [`docs/security-operations/operations/provisioning.mdx`](../docs/security-operations/operations/provisioning.mdx) · [`docs/security-operations/operations/troubleshooting.mdx`](../docs/security-operations/operations/troubleshooting.mdx) · [`docs/security-operations/security/credentials.mdx`](../docs/security-operations/security/credentials.mdx) · [`docs/single-actions/workflow-and-cli.mdx`](../docs/single-actions/workflow-and-cli.mdx) · [`docs/security-operations/operations/verification.mdx`](../docs/security-operations/operations/verification.mdx) · [`docs/development/setup-pat-provider-audit-2026-10-06.md`](../docs/development/setup-pat-provider-audit-2026-10-06.md) · [`docs/issues/comment-commands.mdx`](../docs/issues/comment-commands.mdx) · [`docs/issues/branch-synchronization.mdx`](../docs/issues/branch-synchronization.mdx) · [`docs/setup-web.mdx`](../docs/setup-web.mdx) · [`docs/first-workflow.mdx`](../docs/first-workflow.mdx) · [`docs/using-the-docs.mdx`](../docs/using-the-docs.mdx) · [`docs/guides/index.mdx`](../docs/guides/index.mdx) · [`docs/guides/issues-and-branches.mdx`](../docs/guides/issues-and-branches.mdx) · [`docs/guides/review-pull-requests.mdx`](../docs/guides/review-pull-requests.mdx) · [`docs/guides/work-with-the-bot.mdx`](../docs/guides/work-with-the-bot.mdx) · [`docs/guides/releases-and-hotfixes.mdx`](../docs/guides/releases-and-hotfixes.mdx) · [`docs/agents/repository-collaboration.mdx`](../docs/agents/repository-collaboration.mdx) ### `local-web-setup-assistant` — Local web setup assistant @@ -193,10 +193,10 @@ debt or convert unknown historic intent into a design decision. - Owner: Copilot maintainers - Last verified: 2026-10-21 - Specifications: [`specs/branch-synchronization-and-conflict-recovery.md`](./branch-synchronization-and-conflict-recovery.md) · [`specs/repository-verification-runtime-prerequisites.md`](./repository-verification-runtime-prerequisites.md) · [`specs/repository-verification-setup-hooks.md`](./repository-verification-setup-hooks.md) -- Workflows: [`.github/workflows/copilot_branch_sync.yml`](../.github/workflows/copilot_branch_sync.yml) · [`setup/workflows/copilot_branch_sync.yml`](../setup/workflows/copilot_branch_sync.yml) · [`.github/workflows/copilot_issue.yml`](../.github/workflows/copilot_issue.yml) · [`setup/workflows/copilot_issue.yml`](../setup/workflows/copilot_issue.yml) · [`setup/workflows/copilot_issue_comment.yml`](../setup/workflows/copilot_issue_comment.yml) · [`setup/workflows/copilot_pull_request_comment.yml`](../setup/workflows/copilot_pull_request_comment.yml) +- Workflows: [`.github/workflows/copilot_branch_sync.yml`](../.github/workflows/copilot_branch_sync.yml) · [`setup/workflows/copilot_branch_sync.yml`](../setup/workflows/copilot_branch_sync.yml) · [`.github/workflows/copilot_issue.yml`](../.github/workflows/copilot_issue.yml) · [`setup/workflows/copilot_issue.yml`](../setup/workflows/copilot_issue.yml) · [`setup/workflows/copilot_issue_comment.yml`](../setup/workflows/copilot_issue_comment.yml) · [`setup/workflows/copilot_pull_request_comment.yml`](../setup/workflows/copilot_pull_request_comment.yml) · [`.github/workflows/copilot_comment_runtime.yml`](../.github/workflows/copilot_comment_runtime.yml) · [`.github/workflows/copilot_issue_comment.yml`](../.github/workflows/copilot_issue_comment.yml) · [`.github/workflows/copilot_pull_request_comment.yml`](../.github/workflows/copilot_pull_request_comment.yml) - Entrypoints: [`src/application/usecases/branch_sync/sync_branch_use_case.ts`](../src/application/usecases/branch_sync/sync_branch_use_case.ts) · [`src/application/usecases/actions/observe_branch_sync_use_case.ts`](../src/application/usecases/actions/observe_branch_sync_use_case.ts) -- Core code: [`src/domain/branch_sync_command.ts`](../src/domain/branch_sync_command.ts) · [`src/application/ports/branch_sync_ports.ts`](../src/application/ports/branch_sync_ports.ts) · [`src/application/policies/branch_sync_message_catalog.ts`](../src/application/policies/branch_sync_message_catalog.ts) · [`src/application/policies/branch_sync_notification_policy.ts`](../src/application/policies/branch_sync_notification_policy.ts) · [`src/application/usecases/branch_sync/branch_sync_execution_policy.ts`](../src/application/usecases/branch_sync/branch_sync_execution_policy.ts) · [`src/application/usecases/actions/observe_branch_sync_use_case.ts`](../src/application/usecases/actions/observe_branch_sync_use_case.ts) · [`src/application/usecases/push_single_action_contexts.ts`](../src/application/usecases/push_single_action_contexts.ts) · [`src/application/usecases/steps/common/transition_notification_workflow.ts`](../src/application/usecases/steps/common/transition_notification_workflow.ts) · [`src/data/repository/branch_sync/branch_dependency_policy.ts`](../src/data/repository/branch_sync/branch_dependency_policy.ts) · [`src/data/repository/branch_sync/branch_dependency_repository.ts`](../src/data/repository/branch_sync/branch_dependency_repository.ts) · [`src/infrastructure/composition/main_run_route_composition_root.ts`](../src/infrastructure/composition/main_run_route_composition_root.ts) · [`src/infrastructure/composition/push_single_action_capability_port_binding.ts`](../src/infrastructure/composition/push_single_action_capability_port_binding.ts) · [`src/infrastructure/branch_sync_workspace_adapter.ts`](../src/infrastructure/branch_sync_workspace_adapter.ts) · [`src/prompts/branch_sync_conflicts.ts`](../src/prompts/branch_sync_conflicts.ts) · [`src/data/model/application_error.ts`](../src/data/model/application_error.ts) · [`src/application/policies/application_error_message_catalog.ts`](../src/application/policies/application_error_message_catalog.ts) · [`src/infrastructure/git_commit_adapter.ts`](../src/infrastructure/git_commit_adapter.ts) · [`src/infrastructure/branch_sync_sdd_catalog.ts`](../src/infrastructure/branch_sync_sdd_catalog.ts) · [`src/domain/branch_sync_validation.ts`](../src/domain/branch_sync_validation.ts) · [`src/application/policies/lifecycle_state_policy.ts`](../src/application/policies/lifecycle_state_policy.ts) · [`src/infrastructure/branch_sync_communication_budget.ts`](../src/infrastructure/branch_sync_communication_budget.ts) · [`src/application/usecases/actions/retire_branch_sync_use_case.ts`](../src/application/usecases/actions/retire_branch_sync_use_case.ts) · [`src/application/ports/issue_completion_ports.ts`](../src/application/ports/issue_completion_ports.ts) · [`src/application/usecases/pull_request_workflow.ts`](../src/application/usecases/pull_request_workflow.ts) · [`src/application/usecases/pull_request_workflow_context.ts`](../src/application/usecases/pull_request_workflow_context.ts) · [`src/infrastructure/composition/pull_request_use_case_composition_root.ts`](../src/infrastructure/composition/pull_request_use_case_composition_root.ts) · [`src/actions/common_action.ts`](../src/actions/common_action.ts) · [`src/actions/github_action.ts`](../src/actions/github_action.ts) · [`scripts/validate-workflow-contract.cjs`](../scripts/validate-workflow-contract.cjs) · [`src/application/ports/reply_request_read_ports.ts`](../src/application/ports/reply_request_read_ports.ts) · [`src/domain/reply_request_digest.ts`](../src/domain/reply_request_digest.ts) · [`src/infrastructure/composition/reply_request_composition_root.ts`](../src/infrastructure/composition/reply_request_composition_root.ts) · [`src/data/repository/reply_request_repository.ts`](../src/data/repository/reply_request_repository.ts) · [`src/application/policies/verification_runtime_policy.ts`](../src/application/policies/verification_runtime_policy.ts) · [`src/infrastructure/verification_runtime_manifest.ts`](../src/infrastructure/verification_runtime_manifest.ts) · [`src/infrastructure/verification_runtime_preflight.ts`](../src/infrastructure/verification_runtime_preflight.ts) · [`src/infrastructure/untrusted_command_environment.ts`](../src/infrastructure/untrusted_command_environment.ts) · [`src/application/ports/git_ports.ts`](../src/application/ports/git_ports.ts) · [`src/application/ports/bugbot_git_ports.ts`](../src/application/ports/bugbot_git_ports.ts) · [`src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts`](../src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts) · [`src/application/usecases/steps/commit/bugbot/verify_command_runner.ts`](../src/application/usecases/steps/commit/bugbot/verify_command_runner.ts) · [`src/domain/closed_issue_reconciliation.ts`](../src/domain/closed_issue_reconciliation.ts) · [`src/application/errors/closed_issue_reconciliation_error.ts`](../src/application/errors/closed_issue_reconciliation_error.ts) · [`src/application/policies/verification_setup_policy.ts`](../src/application/policies/verification_setup_policy.ts) · [`src/application/ports/verification_setup_ports.ts`](../src/application/ports/verification_setup_ports.ts) · [`src/infrastructure/verification_setup_snapshot.ts`](../src/infrastructure/verification_setup_snapshot.ts) · [`src/infrastructure/verification_setup_result.ts`](../src/infrastructure/verification_setup_result.ts) · [`src/infrastructure/verification_setup_runner.ts`](../src/infrastructure/verification_setup_runner.ts) · [`src/infrastructure/native_verification_protocol.ts`](../src/infrastructure/native_verification_protocol.ts) · [`src/infrastructure/native_verification_candidate.ts`](../src/infrastructure/native_verification_candidate.ts) · [`src/infrastructure/native_verification_staging.ts`](../src/infrastructure/native_verification_staging.ts) · [`src/infrastructure/native_verification_controller.ts`](../src/infrastructure/native_verification_controller.ts) · [`src/infrastructure/native_verification_profiles.ts`](../src/infrastructure/native_verification_profiles.ts) · [`src/infrastructure/native_verification_redaction.ts`](../src/infrastructure/native_verification_redaction.ts) · [`scripts/generate-native-verification-workflows.cjs`](../scripts/generate-native-verification-workflows.cjs) · [`src/infrastructure/verification_executable.ts`](../src/infrastructure/verification_executable.ts) · [`src/infrastructure/native_verification_source_runtime.ts`](../src/infrastructure/native_verification_source_runtime.ts) · [`scripts/prepare-native-source-action.cjs`](../scripts/prepare-native-source-action.cjs) -- Tests: [`src/application/policies/__tests__/branch_sync_notification_policy.test.ts`](../src/application/policies/__tests__/branch_sync_notification_policy.test.ts) · [`src/application/usecases/actions/__tests__/observe_branch_sync_use_case.test.ts`](../src/application/usecases/actions/__tests__/observe_branch_sync_use_case.test.ts) · [`src/application/usecases/branch_sync/__tests__/sync_branch_use_case.test.ts`](../src/application/usecases/branch_sync/__tests__/sync_branch_use_case.test.ts) · [`src/application/usecases/__tests__/push_single_action_contexts.test.ts`](../src/application/usecases/__tests__/push_single_action_contexts.test.ts) · [`src/application/usecases/steps/common/__tests__/transition_notification_workflow.test.ts`](../src/application/usecases/steps/common/__tests__/transition_notification_workflow.test.ts) · [`src/data/repository/branch_sync/__tests__/branch_dependency_policy.test.ts`](../src/data/repository/branch_sync/__tests__/branch_dependency_policy.test.ts) · [`src/data/repository/branch_sync/__tests__/branch_dependency_repository.test.ts`](../src/data/repository/branch_sync/__tests__/branch_dependency_repository.test.ts) · [`src/infrastructure/__tests__/branch_sync_workspace_adapter.test.ts`](../src/infrastructure/__tests__/branch_sync_workspace_adapter.test.ts) · [`src/infrastructure/composition/__tests__/push_single_action_capability_port_binding.test.ts`](../src/infrastructure/composition/__tests__/push_single_action_capability_port_binding.test.ts) · [`src/application/usecases/branch_sync/__tests__/branch_sync_execution_policy.test.ts`](../src/application/usecases/branch_sync/__tests__/branch_sync_execution_policy.test.ts) · [`src/application/errors/__tests__/application_error.test.ts`](../src/application/errors/__tests__/application_error.test.ts) · [`src/application/policies/__tests__/application_error_presentation_policy.test.ts`](../src/application/policies/__tests__/application_error_presentation_policy.test.ts) · [`src/infrastructure/__tests__/git_commit_adapter.test.ts`](../src/infrastructure/__tests__/git_commit_adapter.test.ts) · [`src/infrastructure/__tests__/branch_sync_sdd_catalog.test.ts`](../src/infrastructure/__tests__/branch_sync_sdd_catalog.test.ts) · [`src/infrastructure/__tests__/branch_sync_generated_bundle_validation.test.ts`](../src/infrastructure/__tests__/branch_sync_generated_bundle_validation.test.ts) · [`src/application/policies/__tests__/branch_sync_lifecycle_recovery.test.ts`](../src/application/policies/__tests__/branch_sync_lifecycle_recovery.test.ts) · [`src/infrastructure/__tests__/branch_sync_resolved_workspace.test.ts`](../src/infrastructure/__tests__/branch_sync_resolved_workspace.test.ts) · [`src/infrastructure/__tests__/branch_sync_communication_budget.test.ts`](../src/infrastructure/__tests__/branch_sync_communication_budget.test.ts) · [`src/application/usecases/actions/__tests__/retire_branch_sync_use_case.test.ts`](../src/application/usecases/actions/__tests__/retire_branch_sync_use_case.test.ts) · [`src/application/usecases/__tests__/pull_request_use_case.test.ts`](../src/application/usecases/__tests__/pull_request_use_case.test.ts) · [`src/actions/__tests__/common_action.test.ts`](../src/actions/__tests__/common_action.test.ts) · [`src/actions/__tests__/github_action.test.ts`](../src/actions/__tests__/github_action.test.ts) · [`src/tooling/__tests__/validate_workflow_contract.test.ts`](../src/tooling/__tests__/validate_workflow_contract.test.ts) · [`src/data/repository/__tests__/reply_request_repository.test.ts`](../src/data/repository/__tests__/reply_request_repository.test.ts) · [`src/infrastructure/composition/__tests__/reply_request_composition_root.test.ts`](../src/infrastructure/composition/__tests__/reply_request_composition_root.test.ts) · [`src/application/policies/__tests__/verification_runtime_policy.test.ts`](../src/application/policies/__tests__/verification_runtime_policy.test.ts) · [`src/infrastructure/__tests__/verification_runtime_preflight.test.ts`](../src/infrastructure/__tests__/verification_runtime_preflight.test.ts) · [`src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts`](../src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts) · [`src/infrastructure/__tests__/untrusted_command_environment.test.ts`](../src/infrastructure/__tests__/untrusted_command_environment.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts) · [`src/tooling/__tests__/verification_runtime_guidance.test.ts`](../src/tooling/__tests__/verification_runtime_guidance.test.ts) · [`src/application/policies/__tests__/verification_setup_policy.test.ts`](../src/application/policies/__tests__/verification_setup_policy.test.ts) · [`src/infrastructure/__tests__/verification_setup_snapshot.test.ts`](../src/infrastructure/__tests__/verification_setup_snapshot.test.ts) · [`src/infrastructure/__tests__/verification_setup_runner.test.ts`](../src/infrastructure/__tests__/verification_setup_runner.test.ts) · [`src/infrastructure/__tests__/verification_setup_configuration.test.ts`](../src/infrastructure/__tests__/verification_setup_configuration.test.ts) · [`src/infrastructure/__tests__/verification_setup_sync.test.ts`](../src/infrastructure/__tests__/verification_setup_sync.test.ts) · [`src/infrastructure/__tests__/native_verification_runner.test.ts`](../src/infrastructure/__tests__/native_verification_runner.test.ts) · [`src/infrastructure/__tests__/native_verification_protocol.test.ts`](../src/infrastructure/__tests__/native_verification_protocol.test.ts) · [`src/infrastructure/__tests__/native_verification_controller.test.ts`](../src/infrastructure/__tests__/native_verification_controller.test.ts) · [`src/infrastructure/__tests__/native_verification_redaction.test.ts`](../src/infrastructure/__tests__/native_verification_redaction.test.ts) · [`src/infrastructure/__tests__/native_verification_workflow.test.ts`](../src/infrastructure/__tests__/native_verification_workflow.test.ts) · [`src/infrastructure/__tests__/native_verification_profiles.test.ts`](../src/infrastructure/__tests__/native_verification_profiles.test.ts) · [`src/infrastructure/__tests__/verification_executable.test.ts`](../src/infrastructure/__tests__/verification_executable.test.ts) · [`src/infrastructure/__tests__/native_verification_post.test.ts`](../src/infrastructure/__tests__/native_verification_post.test.ts) · [`src/infrastructure/__tests__/native_verification_source_runtime.test.ts`](../src/infrastructure/__tests__/native_verification_source_runtime.test.ts) +- Core code: [`src/domain/branch_sync_command.ts`](../src/domain/branch_sync_command.ts) · [`src/application/ports/branch_sync_ports.ts`](../src/application/ports/branch_sync_ports.ts) · [`src/application/policies/branch_sync_message_catalog.ts`](../src/application/policies/branch_sync_message_catalog.ts) · [`src/application/policies/branch_sync_notification_policy.ts`](../src/application/policies/branch_sync_notification_policy.ts) · [`src/application/usecases/branch_sync/branch_sync_execution_policy.ts`](../src/application/usecases/branch_sync/branch_sync_execution_policy.ts) · [`src/application/usecases/actions/observe_branch_sync_use_case.ts`](../src/application/usecases/actions/observe_branch_sync_use_case.ts) · [`src/application/usecases/push_single_action_contexts.ts`](../src/application/usecases/push_single_action_contexts.ts) · [`src/application/usecases/steps/common/transition_notification_workflow.ts`](../src/application/usecases/steps/common/transition_notification_workflow.ts) · [`src/data/repository/branch_sync/branch_dependency_policy.ts`](../src/data/repository/branch_sync/branch_dependency_policy.ts) · [`src/data/repository/branch_sync/branch_dependency_repository.ts`](../src/data/repository/branch_sync/branch_dependency_repository.ts) · [`src/infrastructure/composition/main_run_route_composition_root.ts`](../src/infrastructure/composition/main_run_route_composition_root.ts) · [`src/infrastructure/composition/push_single_action_capability_port_binding.ts`](../src/infrastructure/composition/push_single_action_capability_port_binding.ts) · [`src/infrastructure/branch_sync_workspace_adapter.ts`](../src/infrastructure/branch_sync_workspace_adapter.ts) · [`src/prompts/branch_sync_conflicts.ts`](../src/prompts/branch_sync_conflicts.ts) · [`src/data/model/application_error.ts`](../src/data/model/application_error.ts) · [`src/application/policies/application_error_message_catalog.ts`](../src/application/policies/application_error_message_catalog.ts) · [`src/infrastructure/git_commit_adapter.ts`](../src/infrastructure/git_commit_adapter.ts) · [`src/infrastructure/branch_sync_sdd_catalog.ts`](../src/infrastructure/branch_sync_sdd_catalog.ts) · [`src/domain/branch_sync_validation.ts`](../src/domain/branch_sync_validation.ts) · [`src/application/policies/lifecycle_state_policy.ts`](../src/application/policies/lifecycle_state_policy.ts) · [`src/infrastructure/branch_sync_communication_budget.ts`](../src/infrastructure/branch_sync_communication_budget.ts) · [`src/application/usecases/actions/retire_branch_sync_use_case.ts`](../src/application/usecases/actions/retire_branch_sync_use_case.ts) · [`src/application/ports/issue_completion_ports.ts`](../src/application/ports/issue_completion_ports.ts) · [`src/application/usecases/pull_request_workflow.ts`](../src/application/usecases/pull_request_workflow.ts) · [`src/application/usecases/pull_request_workflow_context.ts`](../src/application/usecases/pull_request_workflow_context.ts) · [`src/infrastructure/composition/pull_request_use_case_composition_root.ts`](../src/infrastructure/composition/pull_request_use_case_composition_root.ts) · [`src/actions/common_action.ts`](../src/actions/common_action.ts) · [`src/actions/github_action.ts`](../src/actions/github_action.ts) · [`scripts/validate-workflow-contract.cjs`](../scripts/validate-workflow-contract.cjs) · [`src/application/ports/reply_request_read_ports.ts`](../src/application/ports/reply_request_read_ports.ts) · [`src/domain/reply_request_digest.ts`](../src/domain/reply_request_digest.ts) · [`src/infrastructure/composition/reply_request_composition_root.ts`](../src/infrastructure/composition/reply_request_composition_root.ts) · [`src/data/repository/reply_request_repository.ts`](../src/data/repository/reply_request_repository.ts) · [`src/application/policies/verification_runtime_policy.ts`](../src/application/policies/verification_runtime_policy.ts) · [`src/infrastructure/verification_runtime_manifest.ts`](../src/infrastructure/verification_runtime_manifest.ts) · [`src/infrastructure/verification_runtime_preflight.ts`](../src/infrastructure/verification_runtime_preflight.ts) · [`src/infrastructure/untrusted_command_environment.ts`](../src/infrastructure/untrusted_command_environment.ts) · [`src/application/ports/git_ports.ts`](../src/application/ports/git_ports.ts) · [`src/application/ports/bugbot_git_ports.ts`](../src/application/ports/bugbot_git_ports.ts) · [`src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts`](../src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts) · [`src/application/usecases/steps/commit/bugbot/verify_command_runner.ts`](../src/application/usecases/steps/commit/bugbot/verify_command_runner.ts) · [`src/domain/closed_issue_reconciliation.ts`](../src/domain/closed_issue_reconciliation.ts) · [`src/application/errors/closed_issue_reconciliation_error.ts`](../src/application/errors/closed_issue_reconciliation_error.ts) · [`src/application/policies/verification_setup_policy.ts`](../src/application/policies/verification_setup_policy.ts) · [`src/application/ports/verification_setup_ports.ts`](../src/application/ports/verification_setup_ports.ts) · [`src/infrastructure/verification_setup_snapshot.ts`](../src/infrastructure/verification_setup_snapshot.ts) · [`src/infrastructure/verification_setup_result.ts`](../src/infrastructure/verification_setup_result.ts) · [`src/infrastructure/verification_setup_runner.ts`](../src/infrastructure/verification_setup_runner.ts) · [`src/infrastructure/native_verification_protocol.ts`](../src/infrastructure/native_verification_protocol.ts) · [`src/infrastructure/native_verification_candidate.ts`](../src/infrastructure/native_verification_candidate.ts) · [`src/infrastructure/native_verification_staging.ts`](../src/infrastructure/native_verification_staging.ts) · [`src/infrastructure/native_verification_controller.ts`](../src/infrastructure/native_verification_controller.ts) · [`src/infrastructure/native_verification_profiles.ts`](../src/infrastructure/native_verification_profiles.ts) · [`src/infrastructure/native_verification_redaction.ts`](../src/infrastructure/native_verification_redaction.ts) · [`scripts/generate-native-verification-workflows.cjs`](../scripts/generate-native-verification-workflows.cjs) · [`src/infrastructure/verification_executable.ts`](../src/infrastructure/verification_executable.ts) · [`src/infrastructure/native_verification_source_runtime.ts`](../src/infrastructure/native_verification_source_runtime.ts) · [`scripts/prepare-native-source-action.cjs`](../scripts/prepare-native-source-action.cjs) · [`src/domain/copilot_comment_workflow.ts`](../src/domain/copilot_comment_workflow.ts) · [`src/infrastructure/copilot_comment_inputs.json`](../src/infrastructure/copilot_comment_inputs.json) · [`scripts/validate-comment-workflows.cjs`](../scripts/validate-comment-workflows.cjs) +- Tests: [`src/application/policies/__tests__/branch_sync_notification_policy.test.ts`](../src/application/policies/__tests__/branch_sync_notification_policy.test.ts) · [`src/application/usecases/actions/__tests__/observe_branch_sync_use_case.test.ts`](../src/application/usecases/actions/__tests__/observe_branch_sync_use_case.test.ts) · [`src/application/usecases/branch_sync/__tests__/sync_branch_use_case.test.ts`](../src/application/usecases/branch_sync/__tests__/sync_branch_use_case.test.ts) · [`src/application/usecases/__tests__/push_single_action_contexts.test.ts`](../src/application/usecases/__tests__/push_single_action_contexts.test.ts) · [`src/application/usecases/steps/common/__tests__/transition_notification_workflow.test.ts`](../src/application/usecases/steps/common/__tests__/transition_notification_workflow.test.ts) · [`src/data/repository/branch_sync/__tests__/branch_dependency_policy.test.ts`](../src/data/repository/branch_sync/__tests__/branch_dependency_policy.test.ts) · [`src/data/repository/branch_sync/__tests__/branch_dependency_repository.test.ts`](../src/data/repository/branch_sync/__tests__/branch_dependency_repository.test.ts) · [`src/infrastructure/__tests__/branch_sync_workspace_adapter.test.ts`](../src/infrastructure/__tests__/branch_sync_workspace_adapter.test.ts) · [`src/infrastructure/composition/__tests__/push_single_action_capability_port_binding.test.ts`](../src/infrastructure/composition/__tests__/push_single_action_capability_port_binding.test.ts) · [`src/application/usecases/branch_sync/__tests__/branch_sync_execution_policy.test.ts`](../src/application/usecases/branch_sync/__tests__/branch_sync_execution_policy.test.ts) · [`src/application/errors/__tests__/application_error.test.ts`](../src/application/errors/__tests__/application_error.test.ts) · [`src/application/policies/__tests__/application_error_presentation_policy.test.ts`](../src/application/policies/__tests__/application_error_presentation_policy.test.ts) · [`src/infrastructure/__tests__/git_commit_adapter.test.ts`](../src/infrastructure/__tests__/git_commit_adapter.test.ts) · [`src/infrastructure/__tests__/branch_sync_sdd_catalog.test.ts`](../src/infrastructure/__tests__/branch_sync_sdd_catalog.test.ts) · [`src/infrastructure/__tests__/branch_sync_generated_bundle_validation.test.ts`](../src/infrastructure/__tests__/branch_sync_generated_bundle_validation.test.ts) · [`src/application/policies/__tests__/branch_sync_lifecycle_recovery.test.ts`](../src/application/policies/__tests__/branch_sync_lifecycle_recovery.test.ts) · [`src/infrastructure/__tests__/branch_sync_resolved_workspace.test.ts`](../src/infrastructure/__tests__/branch_sync_resolved_workspace.test.ts) · [`src/infrastructure/__tests__/branch_sync_communication_budget.test.ts`](../src/infrastructure/__tests__/branch_sync_communication_budget.test.ts) · [`src/application/usecases/actions/__tests__/retire_branch_sync_use_case.test.ts`](../src/application/usecases/actions/__tests__/retire_branch_sync_use_case.test.ts) · [`src/application/usecases/__tests__/pull_request_use_case.test.ts`](../src/application/usecases/__tests__/pull_request_use_case.test.ts) · [`src/actions/__tests__/common_action.test.ts`](../src/actions/__tests__/common_action.test.ts) · [`src/actions/__tests__/github_action.test.ts`](../src/actions/__tests__/github_action.test.ts) · [`src/tooling/__tests__/validate_workflow_contract.test.ts`](../src/tooling/__tests__/validate_workflow_contract.test.ts) · [`src/data/repository/__tests__/reply_request_repository.test.ts`](../src/data/repository/__tests__/reply_request_repository.test.ts) · [`src/infrastructure/composition/__tests__/reply_request_composition_root.test.ts`](../src/infrastructure/composition/__tests__/reply_request_composition_root.test.ts) · [`src/application/policies/__tests__/verification_runtime_policy.test.ts`](../src/application/policies/__tests__/verification_runtime_policy.test.ts) · [`src/infrastructure/__tests__/verification_runtime_preflight.test.ts`](../src/infrastructure/__tests__/verification_runtime_preflight.test.ts) · [`src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts`](../src/infrastructure/__tests__/verification_runtime_branch_sync.test.ts) · [`src/infrastructure/__tests__/untrusted_command_environment.test.ts`](../src/infrastructure/__tests__/untrusted_command_environment.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts) · [`src/tooling/__tests__/verification_runtime_guidance.test.ts`](../src/tooling/__tests__/verification_runtime_guidance.test.ts) · [`src/application/policies/__tests__/verification_setup_policy.test.ts`](../src/application/policies/__tests__/verification_setup_policy.test.ts) · [`src/infrastructure/__tests__/verification_setup_snapshot.test.ts`](../src/infrastructure/__tests__/verification_setup_snapshot.test.ts) · [`src/infrastructure/__tests__/verification_setup_runner.test.ts`](../src/infrastructure/__tests__/verification_setup_runner.test.ts) · [`src/infrastructure/__tests__/verification_setup_configuration.test.ts`](../src/infrastructure/__tests__/verification_setup_configuration.test.ts) · [`src/infrastructure/__tests__/verification_setup_sync.test.ts`](../src/infrastructure/__tests__/verification_setup_sync.test.ts) · [`src/infrastructure/__tests__/native_verification_runner.test.ts`](../src/infrastructure/__tests__/native_verification_runner.test.ts) · [`src/infrastructure/__tests__/native_verification_protocol.test.ts`](../src/infrastructure/__tests__/native_verification_protocol.test.ts) · [`src/infrastructure/__tests__/native_verification_controller.test.ts`](../src/infrastructure/__tests__/native_verification_controller.test.ts) · [`src/infrastructure/__tests__/native_verification_redaction.test.ts`](../src/infrastructure/__tests__/native_verification_redaction.test.ts) · [`src/infrastructure/__tests__/native_verification_workflow.test.ts`](../src/infrastructure/__tests__/native_verification_workflow.test.ts) · [`src/infrastructure/__tests__/native_verification_profiles.test.ts`](../src/infrastructure/__tests__/native_verification_profiles.test.ts) · [`src/infrastructure/__tests__/verification_executable.test.ts`](../src/infrastructure/__tests__/verification_executable.test.ts) · [`src/infrastructure/__tests__/native_verification_post.test.ts`](../src/infrastructure/__tests__/native_verification_post.test.ts) · [`src/infrastructure/__tests__/native_verification_source_runtime.test.ts`](../src/infrastructure/__tests__/native_verification_source_runtime.test.ts) · [`src/domain/__tests__/copilot_comment_workflow.test.ts`](../src/domain/__tests__/copilot_comment_workflow.test.ts) - User documentation: [`docs/issues/branch-synchronization.mdx`](../docs/issues/branch-synchronization.mdx) · [`docs/issues/comment-commands.mdx`](../docs/issues/comment-commands.mdx) · [`docs/issues/notifications-and-auto-close.mdx`](../docs/issues/notifications-and-auto-close.mdx) · [`docs/development/architecture.mdx`](../docs/development/architecture.mdx) · [`docs/security-operations/operations/verification.mdx`](../docs/security-operations/operations/verification.mdx) · [`docs/security-operations/operations/troubleshooting.mdx`](../docs/security-operations/operations/troubleshooting.mdx) · [`docs/agents/repository-collaboration.mdx`](../docs/agents/repository-collaboration.mdx) ### `pull-request-lifecycle` — Pull request lifecycle and enrichment diff --git a/specs/catalog.json b/specs/catalog.json index 0f567c8ab..ccbaae8a8 100644 --- a/specs/catalog.json +++ b/specs/catalog.json @@ -760,7 +760,8 @@ "specs/setup-pat-permission-guidance-and-verification.md", "specs/github-runtime-doctor-command.md", "specs/organization-configuration-reuse-and-batch-setup.md", - "specs/setup-runner-profiles-and-installation-parity.md" + "specs/setup-runner-profiles-and-installation-parity.md", + "specs/copilot-comment-workflow-coordinator.md" ], "workflows": [ "setup/workflows/agent-cli-provisioning.yml", @@ -942,7 +943,9 @@ "src/application/ports/bugbot_git_ports.ts", "src/application/usecases/steps/commit/bugbot/commit_and_push_preflight.ts", "src/application/usecases/steps/commit/bugbot/verify_command_runner.ts", - "src/cli/setup_config_file.ts" + "src/cli/setup_config_file.ts", + "src/domain/copilot_comment_workflow.ts", + "src/infrastructure/copilot_comment_inputs.json" ], "tests": [ "src/data/repository/__tests__/repository_version_tags_query_repository.test.ts", @@ -1073,7 +1076,8 @@ "src/application/usecases/steps/commit/bugbot/__tests__/verify_command_runner.test.ts", "src/application/usecases/steps/commit/bugbot/__tests__/commit_verification_workspace.test.ts", "src/tooling/__tests__/verification_runtime_guidance.test.ts", - "src/infrastructure/__tests__/verification_setup_configuration.test.ts" + "src/infrastructure/__tests__/verification_setup_configuration.test.ts", + "src/domain/__tests__/copilot_comment_workflow.test.ts" ], "documentation": [ "README.md", @@ -1977,7 +1981,10 @@ ".github/workflows/copilot_issue.yml", "setup/workflows/copilot_issue.yml", "setup/workflows/copilot_issue_comment.yml", - "setup/workflows/copilot_pull_request_comment.yml" + "setup/workflows/copilot_pull_request_comment.yml", + ".github/workflows/copilot_comment_runtime.yml", + ".github/workflows/copilot_issue_comment.yml", + ".github/workflows/copilot_pull_request_comment.yml" ], "entrypoints": [ "src/application/usecases/branch_sync/sync_branch_use_case.ts", @@ -2041,7 +2048,10 @@ "scripts/generate-native-verification-workflows.cjs", "src/infrastructure/verification_executable.ts", "src/infrastructure/native_verification_source_runtime.ts", - "scripts/prepare-native-source-action.cjs" + "scripts/prepare-native-source-action.cjs", + "src/domain/copilot_comment_workflow.ts", + "src/infrastructure/copilot_comment_inputs.json", + "scripts/validate-comment-workflows.cjs" ], "tests": [ "src/application/policies/__tests__/branch_sync_notification_policy.test.ts", @@ -2089,7 +2099,8 @@ "src/infrastructure/__tests__/native_verification_profiles.test.ts", "src/infrastructure/__tests__/verification_executable.test.ts", "src/infrastructure/__tests__/native_verification_post.test.ts", - "src/infrastructure/__tests__/native_verification_source_runtime.test.ts" + "src/infrastructure/__tests__/native_verification_source_runtime.test.ts", + "src/domain/__tests__/copilot_comment_workflow.test.ts" ], "documentation": [ "docs/issues/branch-synchronization.mdx", diff --git a/specs/copilot-comment-workflow-coordinator.md b/specs/copilot-comment-workflow-coordinator.md new file mode 100644 index 000000000..99df52d25 --- /dev/null +++ b/specs/copilot-comment-workflow-coordinator.md @@ -0,0 +1,348 @@ +# Copilot Comment Workflow Coordinator + +- Status: Draft +- Date: 2026-10-22 +- Catalog capability ID: setup-and-doctor +- Last verified: not applicable +- Owners: Copilot maintainers +- Scope: Centralize native issue-comment and pull-request-review-comment verification coordination in one versioned Copilot reusable workflow and specify safe consumer setup migration. +- Related issues/PRs: [Issue #662](https://github.com/vypdev/copilot/issues/662); related delivered work #647/#652 and #656/#657; dependent release #661 (3.10.0). +- Required review gates: product UX, architecture, testing, documentation, security/operations +- Open decisions blocking readiness: none + +## 1. Executive summary + +This companion specification defines one Copilot-owned reusable workflow for the complete native verification lifecycle used by issue-comment and pull-request-review-comment callbacks. Repository callbacks and setup templates call one versioned workflow instead of copying twenty setup/continue pairs and cleanup steps. The reusable workflow owns one job, so the existing native per-step timeout and same-job candidate environment remain intact. + +The safety rule is that only admitted, trusted verification work may reach the worker, and continuations verify the existing candidate without rerunning the agent or business operation. Secrets remain explicit and narrowly scoped; project setup receives no provider credentials or PAT inputs. + +```text +Comment callback -> versioned Copilot reusable workflow -> same-job Copilot Action and trusted dependency setup -> continuation and guarded publication -> reverse native post cleanup +``` + +## 2. Problem, current behavior, and evidence + +### 2.1 Problem + +Repository maintainers and Copilot maintainers must review and upgrade duplicated callback orchestration. The native dependency setup has twenty statically declared setup/continue pairs plus final cleanup, adding 579 lines to each distributed callback and duplicating those lines in source workflows. A generated composite coordinator cannot preserve the native per-step timeout because GitHub rejects `timeout-minutes` within composite steps. + +### 2.2 Current behavior + +1. Issue-comment and pull-request-review-comment callbacks admit events using existing bot, fork, and eligibility gates. +2. A native Copilot Action step runs with explicitly supplied configuration and credentials. +3. Native setup/continue steps prepare dependencies, preserve candidate identity, and wait for worker readiness. +4. Verification and publication guards run without rerunning the agent or business operation. +5. Native post actions clean up setup state in reverse order. + +The issue identifies these as current behavior and requires their preservation. Exact implementation-level names and current card text must be confirmed from the owning specifications and workflow evidence during implementation. + +### 2.3 Evidence + +- Code/workflow/documentation references: current comment callbacks and setup templates are catalogued under `setup-and-doctor`; existing setup owner is `specs/setup-runner-profiles-and-installation-parity.md`. The existing native verification owner remains `specs/repository-verification-setup-hooks.md` under `branch-synchronization`; implementation must retain that ownership and add a cross-reference. Catalog paths establish current locations only, not future runtime support. +- Incidents or concrete examples: twenty statically declared setup/continue pairs plus cleanup; 579 added lines per distributed comment callback. +- External primary sources: [GitHub runner action schema](https://github.com/actions/runner/blob/main/src/Runner.Worker/action_yaml.json); [same-repository self-reference announcement](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/). +- Unknowns: none block this design. Exact supported GitHub.com/runner/action-policy conditions must be documented and validated against the platform at implementation time. + +### 2.4 Retrospective classification (as-built baselines only) + +Not applicable: this is a prospective specification, not a reconstruction of an implemented baseline. + +## 3. Actors, surfaces, and terminology + +| Actor | Goal | Entry point | Visible surfaces | +|---|---|---|---| +| Repository maintainer | Install and upgrade compact comment callbacks safely | Setup or workflow maintenance | Workflow files, checks, setup preview and Apply | +| Comment author | Receive existing verification behavior | Issue or review comment | Existing result cards and linked run | +| Copilot operator | Diagnose a failed or incomplete verification | Workflow run | Job Summary, logs, issue/PR state | +| Copilot maintainer | Own central coordination and compatibility | Reusable workflow release | Versioned workflow, tests, docs, release notes | + +A **callback** is the repository-owned workflow triggered by a supported comment event. The **coordinator** is the Copilot reusable workflow that owns all native lifecycle phases in one job. **Candidate** means the existing admitted worker/candidate identity and environment; it is carried through continuation rather than recreated. **Trusted project setup** is the repository-owned composite dependency action. **Source callback** means a callback in Copilot itself and uses an exact same-commit self-repository workflow reference. **Installed callback** means a consumer callback and uses `vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`. + +## 4. Goals + +### 4.1 Goals + +1. Reduce each source and setup comment callback to at most 35 lines while centralizing all native phases in one reusable workflow. +2. Preserve existing admission, verification, publication, result-card, timeout, identity, credential, and cleanup behavior. +3. Let setup preview and Apply show the same runner route and safely recognize known reusable callers during configuration maintenance. +4. Provide actionable, reviewed migration for custom bootstrap steps without silently deleting them. + +### 4.2 Non-goals + +1. Replacing the repository-owned dependency action with a non-composite action. +2. Dispatching candidate setup to another job or rerunning the agent/business operation to continue verification. +3. Removing time limits or changing verification/publication semantics. +4. Publishing minor release #661 as part of this specification; it remains dependent on this work and its final-head review/checks. + +### 4.3 Fixed product/safety invariants + +1. Preserve admission and bot/fork gates, Variable and Secret semantics, twenty setup boundaries, five-minute native setup cancellation, 300-second worker readiness, and 120-minute job budget. +2. Preserve candidate identity, trusted-main Action pinning, credential-free verifier profiles, one-use continuations, and reverse native post cleanup. +3. Keep named Secrets explicit; provider credentials are scoped to the initial Copilot step. No unrestricted secrets inheritance and no provider credential/PAT inputs to project setup. +4. Unknown inputs, unsupported source identity, malformed runner JSON, and dependent expressions fail closed. +5. Do not drop custom bootstrap steps. Require reviewed migration with a concrete recovery path. +6. Require GitHub.com same-repository self-reference support and runner 2.336.0 or newer; the inspected source runner is 2.337.0. Repository Actions policy must allow the required references. + +## 5. Current versus proposed product journey + +| Stage | Current | Proposed | User/operator effect | +|---|---|---|---| +| Callback maintenance | Setup/continue orchestration is copied into callbacks and source workflows | Callback calls one versioned coordinator | Smaller review surface and centralized upgrades | +| Native job execution | Native phases run in callback job | Reusable workflow owns one job and all native phases | Per-step timeout and candidate environment remain available | +| Setup migration | Existing routes and custom bootstrap need to be recognized | Preview and Apply expose the same route; known reusable callers are recognized; custom steps require reviewed migration | No inferred runner access or silent loss of bootstrap | +| Upgrade | Consumers carry duplicated orchestration | Installed callback pins `@v3`; source callback uses exact same-commit self reference | Coordinator upgrades are explicit and reviewable | + +```mermaid +flowchart LR + C[Comment callback] --> W[Versioned Copilot reusable workflow] + W --> A[Same-commit Copilot Action] + A --> S[Trusted project composite setup] + S --> V[Continuation, verification and publication guards] + V --> P[Native reverse post cleanup] +``` + +Text equivalent: comment callback -> one-job reusable coordinator -> same-commit Copilot Action and trusted setup in the same job -> guarded continuation/publication -> reverse native cleanup. + +## 6. Functional behavior and state model + +### 6.1 Happy path + +1. The callback applies the existing event admission and bot/fork gates, then calls the coordinator with only supported named inputs and explicit named Secrets. +2. Source callbacks reference the workflow at the exact same-commit self repository revision. Installed callbacks reference `vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`. +3. The coordinator resolves supported runner routing and executes one job containing the Copilot Action, trusted project composite setup, continuation, verifier/publication guards, and native post cleanup. +4. Continuation consumes the one-use token and existing candidate identity; it does not rerun the agent or business operation. +5. Existing result cards and publication behavior remain unchanged. + +### 6.2 Alternative paths + +- Disabled, read-only, dry-run, and no-op modes retain their current behavior and do not gain side effects through centralization. +- Existing scalar, label, and group runner routes are retained or explicitly replaced during migration; preview and Apply display the same route. +- Unsupported runner configuration or callback identity fails closed with actionable recovery guidance. +- GitHub.com/runner/Actions-policy prerequisites not met: the callback cannot execute the coordinator; report a clear setup/operator error and link to prerequisites and remediation. +- Custom bootstrap steps: migration pauses for review and provides a documented recovery path; no step is silently discarded. + +### 6.3 State machine + +| State | Entered when | User-visible meaning | Allowed next states | Recovery/owner | +|---|---|---|---|---| +| Not admitted | Existing gates reject event | No verification run is started | Terminal | Existing callback behavior | +| Admitted | Event passes existing gates | Verification is starting | Running, failed | Coordinator/operator | +| Running | Native setup and worker proceed | Existing verification is in progress | Verifying, failed, canceled | Coordinator/operator | +| Verifying | One-use continuation resumes existing candidate | Existing candidate is checked | Published, failed, canceled | Coordinator/operator | +| Published | Existing publication guard allows result | Existing result is available | Terminal | Existing publication behavior | +| Failed/canceled | Guard, timeout, platform, or execution failure | Verification did not complete or was blocked | Retry only under existing policy | Operator uses run diagnostics and recovery docs | + +Duplicate and stale events remain subject to existing admission and one-use continuation semantics. Canceled setup runs retain native post cleanup. No continuation re-executes the agent/business operation. + +## 7. User-facing configuration + +| Input | Type | Recommended default | Allowed values/range | Scope/persistence | +|---|---|---|---|---| +| Installed coordinator ref | Workflow reference | `v3` | Reviewed supported version tags | Callback source, committed and upgraded explicitly | +| Source coordinator ref | Workflow reference | Exact same-commit self-repository reference | Exact caller commit only | Source workflow invocation | +| Runner route | Existing scalar/label/group route representation | Preserve configured route | Valid existing route values; malformed JSON and dependent expressions rejected | Repository setup configuration | +| Coordinator secrets | Named Secret bindings | Existing explicit named bindings | Only supported named Secrets | Passed to coordinator; provider credential scope remains initial Copilot step | +| Job budget | Fixed duration | 120 minutes | Not configurable by consumer | Coordinator job | +| Native setup timeout | Fixed duration | 5 minutes per native setup step | Not configurable by consumer | Coordinator step | +| Worker readiness | Fixed duration | 300 seconds | Not configurable by consumer | Coordinator wait | + +Validation MUST reject unknown workflow inputs, malformed runner JSON, dependent expressions, and unsupported source identity. Route handling MUST preserve existing valid scalar/label/group semantics. Configuration preview and Apply MUST expose identical effective routing. Recommended configuration uses the installed `@v3` reference and existing validated route; the source-workflow alternative uses the exact same-commit self reference. Correctness limits, gates, credential scope, and timeout budgets are not configurable. Existing Variable and Secret behavior is preserved; operation-time snapshot/reread behavior must match the current owning contract. + +## 8. Clean Architecture + +### 8.1 Responsibilities and dependency direction + +| Layer/boundary | Owns | Must not own/import | +|---|---|---| +| Domain/pure policy | Known workflow identity, input allowlist, route recognition and validation decisions | GitHub SDK or workflow runtime DTOs | +| Application | Setup preview/Apply and maintenance decisions; immutable semantic inputs/outputs | Concrete runner or GitHub process concerns | +| Adapters/data | Mapping repository configuration and workflow facts into semantic contracts | Product policy or inferred permissions | +| Infrastructure/composition | Reusable workflow wiring, native steps, secrets mapping, runner execution | Decisions that weaken invariant gates | +| Entrypoints | Compact event callback, existing admission and coordinator invocation | Duplicated orchestration | +| Presentation | Setup preview/Apply route display and actionable migration guidance | Mutations or runner-route inference | + +```mermaid +flowchart LR + E[Comment callback] --> W[Reusable workflow entrypoint] + W --> N[Native same-job phases] + A[Setup application policy] --> P[Known-workflow and route policy] + I[Repository/workflow adapters] --> A + A --> U[Preview and Apply presentation] + N --> X[GitHub Actions and trusted composite] +``` + +### 8.2 Contracts, state, and trust boundaries + +- Pure decisions: accepted coordinator identity/version, known reusable caller recognition, supported inputs, and valid runner-route shape. +- Application contracts: setup preview and Apply expose the same effective route and migration outcome; unsupported facts produce explicit errors. +- Semantic ports: read workflow identity/configuration and apply only validated setup changes. +- Durable state/schema ownership: existing repository Variables, Secrets, workflow files, and continuation state retain their existing owners and schemas. +- Concurrency/idempotency strategy: preserve existing admission, one-use continuation, candidate identity, and publication guards. +- Trusted and untrusted inputs: issue/comment payloads, repository configuration, expressions, and workflow inputs are untrusted until validated; only supported named values cross the coordinator boundary. +- Provider error mapping: distinguish unsupported platform/reference/policy from workflow execution failure and provide actionable setup/operator recovery. + +### 8.3 Executable architecture constraints + +A pure known-workflow contract MUST target 100% branch coverage. Automated checks MUST parse workflow YAML and verify one-job native ownership, allowed inputs/Secrets, source and installed reference forms, timeout placement, callback line limits, setup route parity, and absence of unrestricted secrets inheritance or credential/PAT setup inputs. Dependency/contract checks MUST ensure pure policy does not import provider SDKs and setup presentation does not mutate configuration. + +## 9. UI/UX and content contract + +### 9.1 Information hierarchy + +Existing result cards remain unchanged and continue to show current status, completed facts, next transition, action requirement, impact, and inspectable links before technical details. Setup migration guidance leads with the route that will be applied and any human action required. + +### 9.2 Representative primary view + +The coordinator does not introduce a new issue/review card. Existing cards are normative and must be preserved byte/semantically as established by the verification owner. Setup preview should communicate the concrete effective route and migration decision: + +```markdown +## Comment workflow setup preview + +**Current status:** Ready to apply the Copilot comment workflow update. + +**Runner route:** `labels: [self-hosted, linux]` + +**Action required:** Review the listed custom bootstrap migration before applying. + +## Changes + +- [x] The callback will call Copilot's comment coordinator at `v3`. +- [x] The configured runner route is preserved in preview and Apply. +- [ ] Custom bootstrap step requires maintainer review. + +## What happens next + +Apply the reviewed workflow update, then inspect the first run's checks and Job Summary. +``` + +Variants: pending/no action reports that no run is required; action required links to migration review; blocked/failed identifies impact, cause, action, retained configuration and run link; partially complete states which setup files changed and which remain untouched; completed links to the applied workflow and verification run. No new comment or notification is emitted solely for coordinator adoption. + +### 9.3 Issue, PR, and comment behavior + +- Deterministic titles and purpose: preserve the existing result-card titles and purposes exactly. +- What merge/close/retry will do: preserve current callback semantics; rerun/retry follows existing admission and does not resume by rerunning the agent through the continuation path. +- Durable marker and idempotent update policy: retain existing markers and one-use continuation policy. +- Comment/notification budget: no additional comments or notifications due to centralization. +- Labels and checks as supplemental state: preserve existing checks and publication guards. +- Direct links and navigation: existing issue/PR and workflow-run links remain descriptive and usable. + +### 9.4 Accessibility, localization, and responsive behavior + +Preserve the existing locale and fallback contract of result cards. New setup guidance uses plain text, descriptive links, semantic headings and short lists; it remains readable on narrow screens and in light/dark themes. Escape untrusted values and do not render configuration as executable Markdown, mentions, HTML markers, commands, or arbitrary URLs. Diagrams have adjacent text equivalents. + +## 10. Failure, recovery, and cleanup + +| Failure/partial state | User impact | Retained facts | Automatic retry | Required action | Cleanup | +|---|---|---|---|---|---| +| Unsupported ref, runner, or Actions policy | Callback cannot start coordinator | Existing configuration and callback remain | No | Meet documented GitHub.com, runner 2.336.0+, and policy prerequisites | No setup state created | +| Unknown input or malformed route JSON | Setup/run fails closed | Original configuration retained | No | Correct supported input/route; inspect preview | No inferred permissions/routes | +| Setup step times out | Verification cannot continue | Candidate and prior facts remain subject to existing semantics | Existing policy only | Inspect failed step and retry through supported entrypoint | Native reverse post cleanup | +| Worker readiness exceeds 300 seconds | Verification is blocked | Candidate identity retained where existing runtime permits | Existing policy only | Inspect run and use documented recovery | Native cleanup | +| Job reaches 120-minute budget | Job is canceled | Completed facts and logs retained | Existing policy only | Inspect timeout location before retry | Native post cleanup runs where platform permits | +| Custom bootstrap migration is unreviewed | Setup Apply is blocked | Existing workflow/configuration retained | No | Review migration and apply explicitly | No silent deletion | +| Publication guard rejects result | No result is published | Verification evidence retained | No automatic publication retry beyond current contract | Follow existing operator guidance | Setup cleanup completes | + +Errors follow impact -> cause -> action -> retained state and must not claim successful prior effects failed. + +## 11. Security, permissions, and privacy + +1. Preserve existing event admission, bot/fork gates, and least-privilege permissions. Coordinator permissions must be explicit and no broader than the existing native callback contract. +2. Treat workflow inputs, event data, repository configuration, route JSON, and expressions as untrusted. Reject unknown or ambiguous values; never infer runner access. +3. Named Secrets remain explicit. Do not use unrestricted secrets inheritance. Provider credentials are scoped to the initial Copilot step and must not be passed to project setup. +4. Preserve trusted-main Action pinning, candidate identity, credential-free verifier profiles, one-use continuations, and guarded publication. Logs and summaries must not expose Secret values or sensitive environment data. + +## 12. Observability and operational UX + +- User-facing state: existing cards and checks remain the source of verification outcome. +- Job Summary/operator evidence: identify callback type, coordinator version/ref, admitted phase, setup/continuation outcome, verifier/publication guard outcome, and cleanup status without secret values. +- Logs, metrics, and correlation: preserve existing run/event/candidate correlation identifiers and sanitize untrusted fields. +- Pending external dependency versus workflow failure: distinguish platform prerequisite/reference rejection from native step failure. +- Rate-limit/retry behavior: preserve existing provider retry behavior and bounds. +- Noise/comment budget: centralization adds no comments or notifications. + +## 13. Compatibility, migration, rollout, and rollback + +Source callbacks use the exact same-commit self-repository workflow reference. Installed callbacks use `vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3`. The coordinator uses GitHub's self-repository Action reference so an exact caller SHA cannot drift to another Action version. Require GitHub.com support, runner 2.336.0 or later, and compatible Actions policy; document these prerequisites and how to upgrade the pinned workflow ref. + +Migration MUST preserve source-only jobs and consumer Action bytes and auxiliary assets. Setup MUST retain or explicitly replace existing scalar/label/group routes, display the same route in preview and Apply, and recognize known reusable callers during maintenance. Unknown inputs, unsupported source identity, malformed runner JSON, and dependent expressions fail closed. Custom bootstrap steps require reviewed migration and actionable recovery. Rollout follows the Action-managed issue branch and reviewed PR lifecycle; do not create, rename, or force-push managed branches manually. Keep unrelated release-review changes out absent concrete dependency. Release #661 remains unpublished until this dependency and its final-head checks/review are complete. Rollback restores the prior callback workflow and configuration while preserving existing candidate and result facts; no irreversible effect is introduced by the coordinator itself. + +## 14. Testing strategy and numeric budget + +Minimum additional risk-derived floor: 40 distinct cases shared once across both capabilities; do not double count a case because both callback types use it. + +| Area | Minimum distinct cases | Behaviors/risks covered | +|---|---:|---| +| Workflow/security mutations | 16 | Admission/bot/fork gates; explicit secrets; no inherit-all; credential scope; trusted pin; timeouts; one job; same-job candidate; continuation; cleanup; publication guards; input rejection | +| Routing/migration/idempotency | 12 | Scalar/label/group routes; preview/Apply parity; known caller recognition; malformed JSON; dependent expressions; custom bootstrap review; source-only jobs; assets/bytes; replay and one-use semantics | +| Configuration inspection/identity/credential scope | 12 | Known workflow contract; supported source identity; installed ref; unknown input; unsupported runner/platform/policy; Variable/Secret semantics; credential boundary; failure recovery | +| **Total** | **40** | No double counting | + +Repository coverage gates remain in force. Changed modules meet existing thresholds; new pure known-workflow policy targets 100% branch coverage. Tests parse workflow structure rather than grep prose, and cover both callback entrypoints against shared coordinator contracts. Use deterministic fixtures and fakes without real waits or live services. Preserve and extend golden result-card fixtures with semantic assertions. Manual UX evidence reviews setup preview/Apply parity and existing result cards at narrow width and light/dark themes. Full implementation validation includes all repository validators, full coverage, package/build smoke, and real native acceptance on Linux, Windows, and macOS. + +## 15. Documentation and discoverability + +| Audience | Artifact/page | Required content | Validation/navigation | +|---|---|---|---| +| User | `docs/issues/comment-commands.mdx` | Existing result behavior and run links remain unchanged | Documentation link/contract checks | +| Setup owner | `docs/setup-web.mdx`, `docs/configuration.mdx`, `docs/configuration-checklist.mdx` | Coordinator installation, route preview/Apply parity, supported inputs and secrets | Fixtures and documentation validators | +| Operator | `docs/security-operations/operations/verification.mdx`, `docs/security-operations/operations/troubleshooting.mdx` | Prerequisites, failure states, timeout/cleanup, recovery | Operator decision-tree review | +| Contributor | `docs/development/architecture.mdx`, `specs/copilot-comment-workflow-coordinator.md`, both existing owning specs | Boundaries, workflow contracts, pinned-ref upgrades, migration | Architecture and specification validation | + +Update user/operator/upgrade documentation, tests, generated bundles, catalog evidence, and `specs/CATALOG.md` together. Document GitHub.com, runner 2.336.0+, Actions-policy prerequisites and pinned-ref upgrades. Cross-reference the branch-synchronization verification SDD without changing its ownership. Keep examples synchronized with contract fixtures. + +## 16. Acceptance scenarios + +1. Given an admitted issue-comment event, when its callback invokes the installed coordinator, then the existing result and publication behavior completes through one job with the same candidate and cleanup semantics. +2. Given a source callback, when it invokes the coordinator, then the workflow reference resolves to the exact same commit and the Action reference cannot drift. +3. Given a setup with a scalar, label, or group route, when preview and Apply run, then both show and apply the same route. +4. Given malformed runner JSON, dependent expressions, an unknown input, or unsupported source identity, when setup or workflow validation occurs, then it fails closed and gives actionable recovery without inferring permissions. +5. Given a worker continuation, when verification resumes, then the one-use continuation verifies the existing candidate and does not rerun the agent or business operation. +6. Given a native setup timeout, worker readiness timeout, or job timeout, when the run stops, then the configured five-minute, 300-second, and 120-minute limits apply and reverse native post cleanup runs where supported. +7. Given provider Secrets, when the coordinator runs, then named Secrets are explicit, provider credentials reach only the initial Copilot step, and project setup receives no provider/PAT input. +8. Given custom bootstrap steps, when setup migration is previewed, then Apply requires reviewed migration and presents actionable recovery without silently dropping steps. +9. Given disabled, read-only, dry-run, or no-op configuration, when the callback executes, then existing semantics and user-facing cards are retained. +10. Given GitHub.com or runner/Actions-policy prerequisites are unmet, when the callback is invoked, then failure is clear and points to prerequisite remediation. +11. Given the documentation and generated bundles are updated, when repository validation runs, then specification/catalog, workflow, coverage, package/build, and cross-platform native acceptance gates are satisfied. + +## 17. Requirements traceability + +| Requirement | Policy/use case/adapter/presentation | Test or evidence | Documentation | +|---|---|---|---| +| Central coordinator and one-job native lifecycle | Workflow composition | Workflow structure contracts; 16 workflow/security cases | Architecture and verification docs | +| Exact source and installed references | Entrypoint/workflow adapter | Ref identity contract cases | Upgrade guide | +| Preserve route and migration behavior | Setup policy and preview/Apply | 12 routing/migration/idempotency cases | Setup/configuration docs | +| Credential and trust boundaries | Workflow inputs and Secret mapping | 12 identity/credential cases plus security mutations | Security credentials and operations docs | +| Existing behavior and result cards | Existing verification owner and presentation | Golden and semantic compatibility assertions | Comment commands and verification docs | +| Platform prerequisites and recovery | Infrastructure/operator guidance | Platform/ref failure contracts | Troubleshooting and upgrade docs | + +## 18. Implementation sequence + +1. Record workflow input/Secret contracts, supported source identity, runner route rules, and architecture checks. +2. Implement pure known-workflow/input/route policy and achieve full branch coverage. +3. Update setup preview/Apply and configuration maintenance recognition with migration outcomes. +4. Implement the central reusable workflow with all native phases and contract tests. +5. Migrate source and setup callbacks, preserving source-only jobs, Action bytes/assets, and custom bootstrap through reviewed migration. +6. Update both owning specifications by cross-reference/change, catalog evidence, generated bundles, user/operator/upgrade docs, and fixtures together. +7. Run repository validators, full coverage, package/build smoke, and real native acceptance on Linux, Windows, and macOS; obtain review and final-head checks before release dependency proceeds. + +## 19. Definition of Done + +- [ ] Source and setup comment callbacks are each at most 35 lines and one central workflow owns all native phases. +- [ ] Existing admission, bot/fork gates, Variable/Secret semantics, time limits, candidate identity, pinning, verifier profiles, continuation, publication, cards, and cleanup are preserved. +- [ ] No unrestricted secrets inheritance or provider/PAT inputs to project setup; named Secret scope is verified. +- [ ] Setup preview and Apply expose identical routes; known callers are recognized; malformed/unknown/ambiguous inputs fail closed. +- [ ] Custom bootstrap steps have reviewed migration and actionable recovery; source-only jobs, consumer Action bytes, and auxiliary assets are preserved. +- [ ] GitHub.com, runner, Actions-policy prerequisites and pinned-ref upgrades are documented. +- [ ] Numeric 40-case budget passes, existing coverage gates remain, and new pure known-workflow contract has full branch coverage. +- [ ] Linux, Windows, and macOS native acceptance, repository validators, full coverage, and package/build smoke pass. +- [ ] User/setup/operator/contributor and upgrade documentation, owning-spec cross-references, generated bundles, catalog evidence, and `specs/CATALOG.md` are current; `pnpm run validate:specifications` passes. +- [ ] Existing result cards pass UX review; failure, migration, security, cleanup, and accessibility requirements are satisfied. +- [ ] Final-head checks and review are complete before dependent release #661 is published. +- [ ] No readiness-blocking decision remains unresolved. + +## 20. References and decisions + +- Primary sources: [GitHub runner action schema](https://github.com/actions/runner/blob/main/src/Runner.Worker/action_yaml.json); [GitHub same-repository self-reference announcement](https://github.blog/changelog/2026-07-30-reference-same-repository-actions-with-self-repository-syntax/). +- Related specs/ADRs/issues/PRs: [Issue #662](https://github.com/vypdev/copilot/issues/662); existing setup owner `specs/setup-runner-profiles-and-installation-parity.md` under `setup-and-doctor`; existing verification owner `specs/repository-verification-setup-hooks.md` under `branch-synchronization`; #647/#652 and #656/#657; dependent release #661. +- Decisions and rejected alternatives: one reusable workflow owns the complete job; generated orchestration in every consumer rejected for duplication/review cost; composite coordinator rejected because it cannot preserve native per-step cancellation; another candidate setup job rejected because it breaks same-job worker/candidate environment; removing time limits is outside scope. Maintainer approved a concise new companion at `specs/copilot-comment-workflow-coordinator.md` under `setup-and-doctor`. +- Follow-up work explicitly outside this spec: publishing release #661 before this issue's implementation and final-head checks/review; unrelated release-review corrections without a concrete dependency. \ No newline at end of file diff --git a/specs/repository-verification-setup-hooks.md b/specs/repository-verification-setup-hooks.md index 8bc3851e2..fc2ea8e89 100644 --- a/specs/repository-verification-setup-hooks.md +++ b/specs/repository-verification-setup-hooks.md @@ -1,14 +1,14 @@ # Repository-owned native verification setup - Status: Ready for implementation -- Date: 2026-10-21 +- Date: 2026-10-22 - Catalog capability ID: branch-synchronization -- Last verified: 2026-10-21 +- Last verified: 2026-10-22 - Owners: Copilot maintainers - Scope: Prepare authorized repository verification through a trusted native composite action, without editing generated workflows. - Related issues/PRs: [#647](https://github.com/vypdev/copilot/issues/647), [#652](https://github.com/vypdev/copilot/pull/652) - Required review gates: product UX, architecture, testing, documentation, security/operations -- Open decisions blocking readiness: none; the maintainer selected a same-job composite action on 2026-10-21. +- Open decisions blocking readiness: none; the maintainer selected a same-job composite dependency action on 2026-10-21 and centralized reusable-workflow coordination on 2026-10-22. ## 1. Executive summary @@ -19,7 +19,7 @@ Authorized operation -> prepare candidate -> native composite setup -> credential-free runtime preflight -> verification -> publication guards -> push ``` -This replaces the unreleased Node ESM prototype in PR #652. There is no custom YAML interpreter and no reusable-workflow candidate transport. +This replaces the unreleased Node ESM prototype in PR #652. There is no custom YAML interpreter or cross-job candidate transport. A Copilot-owned reusable workflow encapsulates the complete same-job coordination; the dependency action remains consumer-owned and composite. ## 2. Problem, current behavior, and evidence @@ -153,13 +153,13 @@ The 20-command limit, five-minute native setup timeout, snapshot/result/path bou ### 8.2 Contracts, state, and trust boundaries -The session contains bounded non-secret metadata and private operational logs. Worker stdout/stderr redact configured secrets and dynamic masking commands before bytes reach disk; PAT/model credentials are never serialized as log content. Credentials remain in the admitted worker's memory/environment as in the existing Action; child verifier environments remain allowlisted. Session provenance, request UUIDs and one-use responses prevent accidental replay across jobs/candidates. Root Action post-job cleanup owns cancellation and private directory removal. Source callbacks MUST copy their Action manifest, bundled runtime and setup assets outside the mutable candidate before execution; their continuations and post steps use that snapshot. Remote installed Actions already have an independent runner cache. Post hooks run only for the native callback phases, preserving ordinary direct Action behavior. Dependency-only profiles remain private until nested native post steps finish, then the original Action post step removes them; no later verifier reuses them. No artifacts or remote checkpoints are created. +The session contains bounded non-secret metadata and private operational logs. Worker stdout/stderr redact configured secrets and dynamic masking commands before bytes reach disk; PAT/model credentials are never serialized as log content. Credentials remain in the admitted worker's memory/environment as in the existing Action; child verifier environments remain allowlisted. Session provenance, request UUIDs and one-use responses prevent accidental replay across jobs/candidates. Root Action post-job cleanup owns cancellation and private directory removal. The reusable coordinator MUST use GitHub self-repository `$/` references for its initial Action and every continuation/post registration. GitHub resolves these to the called workflow repository and exact commit in its independent Action cache, including when the caller pins a full SHA; candidate files cannot replace this runtime. No second independently moving Action version is permitted. The standalone native acceptance fixture retains its explicitly owned source snapshot. Post hooks run only for the native callback phases, preserving ordinary direct Action behavior. Dependency-only profiles remain private until nested native post steps finish, then the original Action post step removes them; no later verifier reuses them. No artifacts or remote checkpoints are created. The workflow's fixed native phases support at most 20 setup boundaries per operation. Worker log forwarding preserves complete runner-command lines, with a 1-MiB single-line memory bound; this is distinct from native setup logs. Worker outputs are bounded to 256 KiB. ### 8.3 Executable architecture constraints -Existing architecture/dependency tests remain mandatory. The workflow validator MUST compare all native setup/continue/finish steps with the canonical generator, including conditions, timeout, runtime-only env and consistent Action reference/inputs. Source and distributed callbacks MUST agree. All six existing configuration callbacks retain explicit opt-in forwarding. +Existing architecture/dependency tests remain mandatory. The workflow validator MUST compare the central reusable workflow and compact source/distributed callers with the canonical generator, including events, bot/fork admission, explicit secret bindings, permissions, runner routing, conditions, timeout, runtime-only env and same-commit Action references/inputs. All six existing configuration callbacks retain explicit opt-in forwarding. ## 9. UI/UX and content contract @@ -200,7 +200,7 @@ Native setup steps have `timeout-minutes: 5`; the worker also rejects readiness ## 11. Security, permissions, and privacy -Native setup receives only runtime metadata from the private verifier environment, never Copilot's PAT/model inputs or evidence token. Generated workflows MUST keep provider secrets scoped to the initial Copilot Action step, not the job or consumer action. Checkout credentials remain unpersisted. Native actions can use runner facilities required for normal Actions execution; they are reviewed executable maintainer code. +Native setup receives only runtime metadata from the private verifier environment, never Copilot's PAT/model inputs or evidence token. Callers MUST explicitly forward the existing named Secrets to the reusable workflow; unrestricted `secrets: inherit` is not generated. The coordinator MUST keep provider secrets scoped to the initial Copilot Action step, not the job or consumer action. Checkout credentials remain unpersisted. Native actions can use runner facilities required for normal Actions execution; they are reviewed executable maintainer code. This preserves the trusted-runner boundary and makes no OS-sandbox claim: same-user processes and service-level credentials remain an operator trust concern. PATH/JAVA_HOME are validated after setup; arbitrary `GITHUB_ENV` keys do not enter the verifier. Native external action versions and dependency caches are maintained by the repository owner. Nested local `uses` is excluded because its deferred post scripts could otherwise refer to candidate assets outside the trusted staging tree. @@ -223,7 +223,7 @@ Existing installations remain disabled by default. The unreleased `.copilot/veri ## 14. Testing strategy and numeric budget -Minimum **150 distinct automated cases**, allocated without double counting: +Minimum **190 distinct automated cases**, allocated without double counting: | Area | Minimum | Risk | |---|---:|---| @@ -231,10 +231,10 @@ Minimum **150 distinct automated cases**, allocated without double counting: | Trusted snapshot/assets | 22 | Pinning, hashes, file modes, malformed/native metadata | | Native protocol/controller | 36 | Lifecycle, output framing, replay, timeout, cancellation | | Candidate/runner orchestration | 24 | Ordering, fresh profiles, candidate identity, failure gates | -| Workflows/setup contracts | 18 | Native step structure, env, limits, source/distribution, preservation | +| Workflows/setup contracts | 58 | Native step structure, env, limits, source/distribution, preservation | | Real Git/composition integration | 8 | Exact managed ref, merge manifests, abort/push guards | | Runtime result filesystem security | 12 | Bounds, links, containment, races, owned staging | -| **Total** | **150** | Native rewrite adds at least 70 cases beyond retained applicable baseline | +| **Total** | **190** | Native rewrite adds at least 70 cases beyond retained applicable baseline | Repository-wide thresholds remain in force. New pure policy targets 100% branches; changed setup adapters target aggregate 95% lines/statements and 90% branches/functions. Deterministic unit fakes cover runner responses without interpreting YAML. Separate native CI acceptance MUST execute real composite `uses`/`run` steps with Python/pytest and Node/pnpm on hosted Linux, Windows and macOS, asserting candidate changes, trusted-source selection, fresh profiles candidate preservation, source-runtime immutability even after candidate bundle changes, and final post cleanup. Controlled local Git acceptance covers the exact same managed branch and no release. Native CI evidence is additional to the distinct Jest budget. @@ -289,3 +289,15 @@ Repository-wide thresholds remain in force. New pure policy targets 100% branche ## 20. References and decisions The maintainer selected the composite approach in the task on 2026-10-21. [Issue decision record](https://github.com/vypdev/copilot/issues/647#issuecomment-6318551564). Related contracts: `branch-synchronization`, repository verification prerequisites and the shared automated commit pipeline in the specification catalog. A reusable workflow and a Node ESM helper were rejected for this delivery; no second execution mode is retained. + + +### 20.1 Central comment coordinator — issue #662 + +The [coordinator companion](./copilot-comment-workflow-coordinator.md) owns the +incremental 40-case encapsulation contract. Source and installed callbacks call +one Copilot-owned workflow; the whole operation remains in one job. The consumer +dependency action remains composite. The companion defines compact callers, +same-commit self references, named Secret isolation, unchanged timeout/cleanup +behavior, safe runner migration, effective configuration inspection, platform +prerequisites, docs and rollout. This document retains the verifier and trusted +setup execution contract; no cross-job candidate transport is introduced. diff --git a/specs/setup-runner-profiles-and-installation-parity.md b/specs/setup-runner-profiles-and-installation-parity.md index d309e5f26..8b6f35660 100644 --- a/specs/setup-runner-profiles-and-installation-parity.md +++ b/specs/setup-runner-profiles-and-installation-parity.md @@ -507,3 +507,32 @@ isolated fixed version probes and safe blocked recovery. Runner selection does n install project language tools. Existing consumers without the declaration retain legacy verification. This companion owns its shared incremental numeric test budget; do not count it twice across the setup and synchronization capabilities. + + +## Compact comment coordinator amendment — issue #662 + +Comment callbacks now delegate their complete job to the Copilot-owned reusable +workflow specified in [comment coordinator](./copilot-comment-workflow-coordinator.md). +Their reviewed route is serialized in `with.runs-on` JSON instead of a native +job `runs-on` key. The pure `copilot_comment_workflow` contract recognizes only +the known versioned coordinator and the exact source self-repository reference; +YAML and workspace adapters retain parsing, migration, preview and Apply. + +Setup MUST retain scalar/label/group routes from both old native jobs and new +coordinator calls, apply explicit profile precedence, show the same per-role +routing in review, and write exactly the reviewed YAML. Dynamic or malformed +runner input MUST block rather than fall back. Source self-repository callbacks +remain complete source-owned assets. Custom legacy bootstrap steps MUST require +reviewed migration before switching job shapes; no steps may silently disappear. +Known reusable installation inspection MUST preserve effective Variable/default +and literal override semantics without reading Secret values or claiming an +unverified local Action identity. Runner 2.336.0+ and GitHub platform support are +additional coordinator prerequisites, not evidence of access or capacity. + +Verification maps these requirements to the new pure contract cases, comment +upgrade cases, installation reader cases and preview/Apply parity fixture. Their +shared incremental **40-case** budget is owned by the native-setup amendment and +is not counted twice here. Existing role isolation, coverage gates, receipts, +backup and recovery remain unchanged. Update verification, upgrade and runner +operations docs, regenerate catalog evidence/bundles, and pass all validators +before publication. diff --git a/src/domain/__tests__/copilot_comment_workflow.test.ts b/src/domain/__tests__/copilot_comment_workflow.test.ts new file mode 100644 index 000000000..daa4e24ef --- /dev/null +++ b/src/domain/__tests__/copilot_comment_workflow.test.ts @@ -0,0 +1,35 @@ +import { copilotCommentRunner, isCopilotCommentWorkflow, isCopilotCommentRunner, COPILOT_COMMENT_REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW } from '../copilot_comment_workflow'; + +describe('known comment coordination and runner contract', () => { + it.each([COPILOT_COMMENT_REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW, + 'vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3.10.0', + `vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@${'a'.repeat(40)}`])('recognizes the reviewed workflow %s', value => { + expect(isCopilotCommentWorkflow(value)).toBe(true); + }); + it.each([undefined, 42, './', 'vypdev/copilot@v3', 'other/copilot/.github/workflows/copilot_comment_runtime.yml@v3', + 'vypdev/copilot/.github/workflows/other.yml@v3', 'vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@master', + 'vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v4'])('does not interpret arbitrary workflow inputs as a runner: %s', value => { + expect(isCopilotCommentWorkflow(value)).toBe(false); + }); + it('retains ordinary native-job routing', () => { + expect(copilotCommentRunner({ 'runs-on': ['self-hosted', 'Linux'] })).toEqual(['self-hosted', 'Linux']); + expect(copilotCommentRunner(undefined)).toBeUndefined(); + }); + it.each(['ubuntu-latest', ['self-hosted', 'codex', 'Linux'], { group: 'trusted', labels: ['self-hosted', 'Linux'] }])('reads the exact reusable route %j', route => { + expect(copilotCommentRunner({ uses: COPILOT_COMMENT_REMOTE_WORKFLOW, with: { 'runs-on': JSON.stringify(route) } })).toEqual(route); + }); + it.each([undefined, {}, { 'runs-on': 42 }, { 'runs-on': 'invalid json' }, { 'runs-on': 'null' }])('blocks missing or malformed reusable routing %j', inputs => { + expect(() => copilotCommentRunner({ uses: COPILOT_COMMENT_REMOTE_WORKFLOW, with: inputs })).toThrow('review the workflow'); + }); + it.each(['ubuntu-latest', ['self-hosted', 'Linux'], { group: 'trusted' }, { labels: 'ubuntu-latest' }, { labels: ['self-hosted', 'macOS'] }])('accepts literal supported routing %j', route => { + expect(isCopilotCommentRunner(route)).toBe(true); + }); + it.each([undefined, null, true, 42, '', ' leading', 'trailing ', '${{ matrix.os }}', 'x'.repeat(101), 'line\nbreak', + [], [''], ['Linux', 'linux'], Array.from({ length: 11 }, (_, index) => `label-${index}`), ['good', 42], {}, + { group: undefined }, { unknown: 'route' }, { group: '' }, { group: 'trusted', labels: [] }, { labels: true }])('rejects invalid or ambiguous routing %j', route => { + expect(isCopilotCommentRunner(route)).toBe(false); + }); + it('rejects oversized JSON before parsing it', () => { + expect(() => copilotCommentRunner({ uses: COPILOT_COMMENT_REMOTE_WORKFLOW, with: { 'runs-on': ' '.repeat(16_001) } })).toThrow('review'); + }); +}); diff --git a/src/domain/copilot_comment_workflow.ts b/src/domain/copilot_comment_workflow.ts new file mode 100644 index 000000000..66bb3c8d0 --- /dev/null +++ b/src/domain/copilot_comment_workflow.ts @@ -0,0 +1,39 @@ +/** The comment coordinator is a versioned Copilot workflow, not an arbitrary reusable job. */ +export const COPILOT_COMMENT_RUNTIME = 'copilot_comment_runtime.yml'; +export const COPILOT_COMMENT_SELF_WORKFLOW = `$/.github/workflows/${COPILOT_COMMENT_RUNTIME}`; +export const COPILOT_COMMENT_REMOTE_WORKFLOW = `vypdev/copilot/.github/workflows/${COPILOT_COMMENT_RUNTIME}@v3`; + +export function isCopilotCommentWorkflow(value: unknown): value is string { + return typeof value === 'string' && (value === COPILOT_COMMENT_SELF_WORKFLOW + || /^vypdev\/copilot\/\.github\/workflows\/copilot_comment_runtime\.yml@(?:v3(?:\.[0-9]+\.[0-9]+)?|[a-f0-9]{40})$/u.test(value)); +} + +const literal = (value: unknown): value is string => typeof value === 'string' && value.length > 0 && value.length <= 100 + && value === value.trim() && !/[\p{Cc}\p{Cf}${}<>]/u.test(value); +const labels = (value: unknown): boolean => literal(value) || Array.isArray(value) && value.length > 0 && value.length <= 10 + && value.every(literal) && new Set(value.map(label => label.toLowerCase())).size === value.length; + +/** Runner routing is literal data; expressions need their original full workflow reviewed. */ +export function isCopilotCommentRunner(value: unknown): boolean { + if (labels(value)) return true; + if (!value || typeof value !== 'object' || Array.isArray(value)) return false; + const route = value as Record; + const keys = Object.keys(route); + return keys.length > 0 && (route.group !== undefined || route.labels !== undefined) + && keys.every(key => key === 'group' || key === 'labels') + && (route.group === undefined || literal(route.group)) + && (route.labels === undefined || labels(route.labels)); +} + +export function copilotCommentRunner(job: Record | undefined): unknown { + if (!job || !isCopilotCommentWorkflow(job.uses)) return job?.['runs-on']; + const inputs = job.with as Record | undefined; + if (typeof inputs?.['runs-on'] !== 'string') throw new Error('Comment workflow runner JSON is unavailable; review the workflow separately.'); + try { + if (inputs['runs-on'].length > 16_000) throw new Error('Runner JSON exceeds its bound.'); + const route: unknown = JSON.parse(inputs['runs-on']); + if (!isCopilotCommentRunner(route)) throw new Error('Unsupported execution route.'); + return route; + } + catch { throw new Error('Comment workflow runner JSON is invalid; review the workflow separately.'); } +} diff --git a/src/infrastructure/__tests__/native_verification_workflow.test.ts b/src/infrastructure/__tests__/native_verification_workflow.test.ts index a127183ad..9389b4aaf 100644 --- a/src/infrastructure/__tests__/native_verification_workflow.test.ts +++ b/src/infrastructure/__tests__/native_verification_workflow.test.ts @@ -2,32 +2,93 @@ import fs from 'node:fs'; import path from 'node:path'; import { load } from 'js-yaml'; const { assertNativeVerificationWorkflow } = require('../../../scripts/validate-workflow-contract.cjs') as { assertNativeVerificationWorkflow(file: string, workflow: any): void }; -const { MAX_REQUESTS, phaseSteps } = require('../../../scripts/generate-native-verification-workflows.cjs') as {MAX_REQUESTS: number; phaseSteps(action: string): any[]}; +const { MAX_REQUESTS, phaseSteps, RUNTIME, SELF_ACTION, runtimeWorkflow } = require('../../../scripts/generate-native-verification-workflows.cjs') as { + MAX_REQUESTS: number; phaseSteps(action: string): any[]; RUNTIME: string; SELF_ACTION: string; runtimeWorkflow(): any; +}; +const read = (directory: string, name: string): {file: string; workflow: any} => { + const file = path.join(process.cwd(), directory, name); + return { file, workflow: load(fs.readFileSync(file, 'utf8')) }; +}; -describe('native verification workflow contract', () => { - it.each(['.github/workflows', 'setup/workflows'])('parses canonical native YAML and anchors from %s', directory => { - for (const name of ['copilot_issue_comment.yml', 'copilot_pull_request_comment.yml']) { - const file = path.join(process.cwd(), directory, name); const workflow = load(fs.readFileSync(file, 'utf8')); +describe('encapsulated native verification workflow contract', () => { + it.each(['.github/workflows', 'setup/workflows'].flatMap(directory => ['copilot_issue_comment.yml', 'copilot_pull_request_comment.yml'].map(name => [directory, name])))( + 'keeps %s/%s as one compact call without phase or credential environment leakage', (directory, name) => { + const { file, workflow } = read(directory, name); expect(() => assertNativeVerificationWorkflow(file, workflow)).not.toThrow(); - } + expect(fs.readFileSync(file, 'utf8').split('\n').length).toBeLessThanOrEqual(35); + const job = Object.values(workflow.jobs)[0] as any; + expect(job.steps).toBeUndefined(); expect(job.env).toBeUndefined(); + expect(job.secrets.PAT).toBe('${{ secrets.PAT }}'); + }); + it('parses the single central native workflow including shared input anchors', () => { + const { file, workflow } = read('.github/workflows', RUNTIME); + expect(workflow).toEqual(runtimeWorkflow()); + expect(() => assertNativeVerificationWorkflow(file, workflow)).not.toThrow(); + }); + it.each(['.github/workflows', 'setup/workflows'])('accepts a reviewed group route in %s without changing other boundaries', directory => { + const { file, workflow } = read(directory, 'copilot_issue_comment.yml'); + const job = Object.values(workflow.jobs)[0] as any; + job.with['runs-on'] = JSON.stringify({ group: 'trusted', labels: ['self-hosted', 'codex', 'Linux'] }); + expect(() => assertNativeVerificationWorkflow(file, workflow)).not.toThrow(); + }); + it('rejects source routing that loses its agent role', () => { + const { file, workflow } = read('.github/workflows', 'copilot_issue_comment.yml'); + const job = Object.values(workflow.jobs)[0] as any; + job.with['runs-on'] = JSON.stringify(['self-hosted', 'unrelated']); + expect(() => assertNativeVerificationWorkflow(file, workflow)).toThrow('codex role'); }); - it('has exactly twenty native setup slots and one completion, with five-minute native timeouts', () => { - const steps = phaseSteps('./'); expect(MAX_REQUESTS).toBe(20); expect(steps).toHaveLength(41); + it('retains twenty setup slots, five-minute native cancellation and a final cleanup', () => { + const steps = phaseSteps(SELF_ACTION); expect(MAX_REQUESTS).toBe(20); expect(steps).toHaveLength(41); expect(steps.filter(step => step.uses === './.git/copilot-verification-setup').every(step => step['timeout-minutes'] === 5)).toBe(true); + expect(steps.at(-1).env.COPILOT_NATIVE_PHASE).toBe('finish'); + expect(steps.at(-1).if).toContain('always()'); }); - it.each(['timeout', 'env', 'condition', 'reference', 'request', 'outcome', 'finish', 'extra', 'remove', 'prepare'])('rejects a weakened %s contract', kind => { - const file = path.join(process.cwd(), 'setup/workflows/copilot_issue_comment.yml'); const workflow = load(fs.readFileSync(file, 'utf8')) as any; - const job = Object.values(workflow.jobs)[0] as any; const start = job.steps.findIndex((step: any) => step.id === 'copilot'); const steps = job.steps; - if (kind === 'timeout') steps[start + 1]['timeout-minutes'] = 60; - if (kind === 'env') steps[start + 1].env.OPENAI_API_KEY = '${{ secrets.OPENAI_API_KEY }}'; - if (kind === 'condition') steps[start + 1].if = '${{ always() }}'; - if (kind === 'reference') steps[start + 2].uses = 'vypdev/copilot@other'; - if (kind === 'request') steps[start + 2].env.COPILOT_NATIVE_REQUEST = 'stale'; - if (kind === 'outcome') steps[start + 2].env.COPILOT_NATIVE_OUTCOME = 'success'; - if (kind === 'finish') steps[steps.length - 1].if = '${{ success() }}'; - if (kind === 'extra') steps.push({run: 'echo bypass'}); - if (kind === 'remove') steps.splice(start + 1, 2); - if (kind === 'prepare') delete steps[start].env.COPILOT_NATIVE_PHASE; - expect(() => assertNativeVerificationWorkflow(file, workflow)).toThrow(/native/u); + it('binds every phase to the called workflow commit without a second version or mutable checkout', () => { + const workflow = runtimeWorkflow(); const phases = workflow.jobs.copilot.steps.filter((step: any) => step.uses === SELF_ACTION); + expect(phases).toHaveLength(22); + expect(phases.every((step: any) => step.with === phases[0].with)).toBe(true); + expect(JSON.stringify(workflow)).not.toContain('vypdev/copilot@'); + expect(JSON.stringify(workflow)).not.toContain('COPILOT_NATIVE_RUNTIME_CACHE'); + }); + it('scopes provider credentials to the initial phase and keeps setup runtime-only', () => { + const job = runtimeWorkflow().jobs.copilot; + expect(JSON.stringify(job.env)).not.toContain('secrets.'); + const credentialSteps = job.steps.filter((step: any) => Object.values(step.env ?? {}).some(value => String(value).includes('secrets.'))); + expect(credentialSteps.map((step: any) => step.id)).toEqual(['copilot']); + for (const step of job.steps.filter((step: any) => step.uses === './.git/copilot-verification-setup')) { + expect(step.with).toBeUndefined(); + expect(Object.keys(step.env).sort()).toEqual(['HOME', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'PATH', 'JAVA_HOME', 'TMP', 'TEMP', 'TMPDIR'].sort()); + } }); + it.each(['timeout', 'env', 'condition', 'reference', 'request', 'outcome', 'finish', 'extra', 'remove', 'prepare', 'initial-source', 'credential-scope'])( + 'rejects a weakened central %s contract', kind => { + const { file, workflow } = read('.github/workflows', RUNTIME); + const steps = workflow.jobs.copilot.steps; const start = steps.findIndex((step: any) => step.id === 'copilot'); + if (kind === 'timeout') steps[start + 1]['timeout-minutes'] = 60; + if (kind === 'env') steps[start + 1].env.OPENAI_API_KEY = '${{ secrets.OPENAI_API_KEY }}'; + if (kind === 'condition') steps[start + 1].if = '${{ always() }}'; + if (kind === 'reference') steps[start + 2].uses = 'vypdev/copilot@other'; + if (kind === 'request') steps[start + 2].env.COPILOT_NATIVE_REQUEST = 'stale'; + if (kind === 'outcome') steps[start + 2].env.COPILOT_NATIVE_OUTCOME = 'success'; + if (kind === 'finish') steps.at(-1).if = '${{ success() }}'; + if (kind === 'extra') steps.push({ run: 'echo bypass' }); + if (kind === 'remove') steps.splice(start + 1, 2); + if (kind === 'prepare') delete steps[start].env.COPILOT_NATIVE_PHASE; + if (kind === 'initial-source') steps[start].uses = './'; + if (kind === 'credential-scope') workflow.jobs.copilot.env.OPENAI_API_KEY = '${{ secrets.OPENAI_API_KEY }}'; + expect(() => assertNativeVerificationWorkflow(file, workflow)).toThrow(/native/u); + }); + it.each(['steps', 'env', 'permissions', 'secrets', 'reference', 'events', 'gate', 'runner'])( + 'rejects a caller that changes the %s boundary', kind => { + const { file, workflow } = read('setup/workflows', 'copilot_pull_request_comment.yml'); const job = workflow.jobs['copilot-pull-requests']; + if (kind === 'steps') job.steps = [{ run: 'true' }]; + if (kind === 'env') job.env = { OPENAI_API_KEY: '${{ secrets.OPENAI_API_KEY }}' }; + if (kind === 'permissions') job.permissions.actions = 'write'; + if (kind === 'secrets') job.secrets = 'inherit'; + if (kind === 'reference') job.uses = job.uses.replace('@v3', '@master'); + if (kind === 'events') workflow.on.pull_request_review_comment.types = ['created']; + if (kind === 'gate') job.if = '${{ always() }}'; + if (kind === 'runner') job.with['runs-on'] = 'not-json'; + expect(() => assertNativeVerificationWorkflow(file, workflow)).toThrow(/native/u); + }); }); diff --git a/src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts b/src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts index 6335523e1..444e20204 100644 --- a/src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts +++ b/src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts @@ -2,6 +2,7 @@ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, symlinkSync } from 'node import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { SetupManagementWorkspaceAdapter } from '../setup_management_workspace_adapter'; +import { COPILOT_COMMENT_REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW } from '../../domain/copilot_comment_workflow'; const roots: string[] = []; function fixture(source?: string) { const root = mkdtempSync(join(tmpdir(), 'copilot-management-')); roots.push(root); const directory = join(root, '.github', 'workflows'); mkdirSync(directory, { recursive: true }); if (source !== undefined) writeFileSync(join(directory, 'copilot.yml'), source); return { root, directory, adapter: new SetupManagementWorkspaceAdapter(root, () => 'revision-a') }; } const workflow = (inputs: string, extra = '') => `name: Copilot @@ -77,3 +78,44 @@ test('multiple local workflows retain the same Action evidence and all input bin writeFileSync(join(f.root,'action.yml'), 'name: Copilot - GitHub with super powers\ninputs:\n bugbot-comment-limit: {default: 20}\n'); expect(f.adapter.inspect()).toMatchObject({ unreadable:false, localActionDigest:expect.any(String), workflows:[{file:'copilot.yml',action:'./'},{file:'second.yml',action:'./'}] }); }); + +describe('reusable comment installation inspection', () => { + const reusable = (uses = COPILOT_COMMENT_REMOTE_WORKFLOW, inputs = '') => `jobs:\n comments:\n uses: ${uses}\n with:\n runs-on: '"ubuntu-latest"'\n${inputs}\n secrets:\n PAT: \${{ secrets.PAT }}\n`; + test.each(['v3', 'v3.10.0', 'a'.repeat(40)])('reads effective Variable defaults from the known coordinator at %s without copying Secrets', ref => { + const f = fixture(reusable(COPILOT_COMMENT_REMOTE_WORKFLOW.replace('@v3', '@' + ref))); + const result = f.adapter.inspect(); + expect(result.unreadable).toBe(false); + expect(result.workflows[0]).toMatchObject({ action: `vypdev/copilot@${ref}`, inputs: expect.arrayContaining([ + { name: 'bugbot-comment-limit', variable: 'BUGBOT_COMMENT_LIMIT', fallback: '20' }, + { name: 'verification-setup', variable: 'VERIFICATION_SETUP', fallback: 'false' }, + ]) }); + expect(JSON.stringify(result)).not.toContain('secrets.'); expect(result.workflows[0].inputs.some(input => input.name === 'token')).toBe(false); + }); + test('retains explicit and empty caller overrides with their actual precedence', () => { + const f = fixture(reusable(COPILOT_COMMENT_REMOTE_WORKFLOW, " pre-branch-sdd: 'true'\n ai-ignore-files: ''")); + expect(f.adapter.inspect().workflows[0].inputs).toEqual(expect.arrayContaining([ + { name: 'pre-branch-sdd', literal: 'true' }, { name: 'ai-ignore-files', variable: 'AI_IGNORE_FILES', fallback: 'build/*' }, + ])); + }); + test('unknown caller inputs block guessed effective configuration', () => { + expect(fixture(reusable(COPILOT_COMMENT_REMOTE_WORKFLOW, ' unknown-input: true')).adapter.inspect()).toMatchObject({ unreadable: true, workflows: [] }); + }); + test.each(['master', 'v4', ''])('an unsupported coordinator ref %s cannot disappear from installation evidence', ref => { + const f = fixture(reusable(COPILOT_COMMENT_REMOTE_WORKFLOW.replace('@v3', '@' + ref))); + writeFileSync(join(f.directory, 'other.yml'), workflow('bugbot-comment-limit: 20')); + expect(f.adapter.inspect()).toMatchObject({ unreadable: true, workflows: [{ file: 'other.yml', action: 'vypdev/copilot@v3' }] }); + }); + test('an unverified workspace-relative coordinator cannot be treated as absent', () => { + expect(fixture(reusable(COPILOT_COMMENT_SELF_WORKFLOW.replace('$/', './'))).adapter.inspect()).toMatchObject({ unreadable: true, workflows: [] }); + }); + test('a self-repository call without known Copilot metadata fails closed', () => { + expect(fixture(reusable(COPILOT_COMMENT_SELF_WORKFLOW)).adapter.inspect()).toMatchObject({ unreadable: true, workflows: [] }); + }); + test('a verified source coordinator binds the local Action metadata and explicit source policy', () => { + const f = fixture(reusable(COPILOT_COMMENT_SELF_WORKFLOW, " pre-branch-sdd: 'true'")); + writeFileSync(join(f.root, 'action.yml'), 'name: Copilot - GitHub with super powers\ninputs:\n bugbot-comment-limit: {default: 20}\n'); + expect(f.adapter.inspect()).toMatchObject({ unreadable: false, localActionDigest: expect.any(String), workflows: [ + { action: './', inputs: expect.arrayContaining([{ name: 'pre-branch-sdd', literal: 'true' }]) }, + ] }); + }); +}); diff --git a/src/infrastructure/__tests__/verification_setup_configuration.test.ts b/src/infrastructure/__tests__/verification_setup_configuration.test.ts index 1f4350a48..2ba87975b 100644 --- a/src/infrastructure/__tests__/verification_setup_configuration.test.ts +++ b/src/infrastructure/__tests__/verification_setup_configuration.test.ts @@ -40,8 +40,17 @@ describe('verification setup installation contract', () => { it.each(['copilot_issue.yml', 'copilot_issue_comment.yml', 'copilot_pull_request.yml', 'copilot_pull_request_comment.yml', 'copilot_pull_request_review_state.yml', 'copilot_commit.yml'])( 'keeps source and distributed %s opt-in explicit and disabled by default', name => { for (const directory of ['.github/workflows', 'setup/workflows']) { - const workflow = yaml.load(fs.readFileSync(path.resolve(__dirname, '../../..', directory, name), 'utf8')) as {jobs: Record}[]}>}; - const actions = Object.values(workflow.jobs).flatMap(job => job.steps).filter(step => step.uses === './' || step.uses === './../.copilot-native-runtime' || step.uses?.startsWith('vypdev/copilot@')); + type Workflow = {jobs: Record; steps?: {uses?: string; with?: Record}[]}>}; + let workflow = yaml.load(fs.readFileSync(path.resolve(__dirname, '../../..', directory, name), 'utf8')) as Workflow; + if (name === 'copilot_issue_comment.yml' || name === 'copilot_pull_request_comment.yml') { + const caller = Object.values(workflow.jobs)[0]; + expect(caller.uses).toBe(directory.startsWith('setup/') + ? 'vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3' + : '$/.github/workflows/copilot_comment_runtime.yml'); + expect(caller.with?.['verification-setup']).toBeUndefined(); + workflow = yaml.load(fs.readFileSync(path.resolve(__dirname, '../../../.github/workflows/copilot_comment_runtime.yml'), 'utf8')) as Workflow; + } + const actions = Object.values(workflow.jobs).flatMap(job => job.steps ?? []).filter(step => step.uses === '$/' || step.uses === './' || step.uses?.startsWith('vypdev/copilot@')); expect(actions.length).toBeGreaterThan(0); for (const action of actions) expect(action.with?.['verification-setup']).toBe("${{ vars.VERIFICATION_SETUP || 'false' }}"); } diff --git a/src/infrastructure/copilot_comment_inputs.json b/src/infrastructure/copilot_comment_inputs.json new file mode 100644 index 000000000..8cdba0db1 --- /dev/null +++ b/src/infrastructure/copilot_comment_inputs.json @@ -0,0 +1,72 @@ +{ + "repository-locale": "${{ vars.REPOSITORY_LOCALE || 'en-US' }}", + "issues-locale": "${{ vars.ISSUES_LOCALE || '' }}", + "pull-requests-locale": "${{ vars.PULL_REQUESTS_LOCALE || '' }}", + "ai-ignore-files": "${{ vars.AI_IGNORE_FILES || 'build/*' }}", + "debug": "${{ vars.DEBUG }}", + "main-branch": "${{ vars.MAIN_BRANCH || 'master' }}", + "development-branch": "${{ vars.DEVELOPMENT_BRANCH || 'develop' }}", + "feature-tree": "${{ vars.FEATURE_TREE || 'feature' }}", + "bugfix-tree": "${{ vars.BUGFIX_TREE || 'bugfix' }}", + "hotfix-tree": "${{ vars.HOTFIX_TREE || 'hotfix' }}", + "release-tree": "${{ vars.RELEASE_TREE || 'release' }}", + "docs-tree": "${{ vars.DOCS_TREE || 'docs' }}", + "chore-tree": "${{ vars.CHORE_TREE || 'chore' }}", + "issue-managed-branches": "${{ vars.ISSUE_MANAGED_BRANCHES || 'true' }}", + "pre-branch-sdd": "${{ vars.PRE_BRANCH_SDD || 'false' }}", + "verification-setup": "${{ vars.VERIFICATION_SETUP || 'false' }}", + "issue-workflow-profile": "${{ vars.COPILOT_ISSUE_WORKFLOW_PROFILE || '' }}", + "reopen-issue-on-push": "${{ vars.REOPEN_ISSUE_ON_PUSH || 'true' }}", + "desired-assignees-count": "${{ vars.DESIRED_ASSIGNEES_COUNT || '1' }}", + "desired-reviewers-count": "${{ vars.DESIRED_REVIEWERS_COUNT || '1' }}", + "commit-prefix-transforms": "${{ vars.COMMIT_PREFIX_TRANSFORMS || 'replace-slash' }}", + "ai-pull-request-description-mode": "${{ vars.AI_PULL_REQUEST_DESCRIPTION_MODE || 'replace' }}", + "ai-members-only": "${{ vars.AI_MEMBERS_ONLY || 'false' }}", + "ai-include-reasoning": "${{ vars.AI_INCLUDE_REASONING || 'false' }}", + "bugbot-severity": "${{ vars.BUGBOT_SEVERITY || 'low' }}", + "bugbot-comment-limit": "${{ vars.BUGBOT_COMMENT_LIMIT || '20' }}", + "bugbot-fix-verify-commands": "${{ vars.BUGBOT_AUTOFIX_VERIFY_COMMANDS }}", + "bugbot-dry-run": "${{ vars.BUGBOT_DRY_RUN || 'false' }}", + "bugbot-effort": "${{ vars.BUGBOT_EFFORT || 'smart' }}", + "bugbot-review-drafts": "${{ vars.BUGBOT_REVIEW_DRAFTS || 'false' }}", + "bugbot-trace-rules": "${{ vars.BUGBOT_TRACE_RULES || 'false' }}", + "bugbot-suggested-changes": "${{ vars.BUGBOT_SUGGESTED_CHANGES || 'true' }}", + "bugbot-telemetry": "${{ vars.BUGBOT_TELEMETRY || 'true' }}", + "bugbot-fail-on-unresolved": "${{ vars.BUGBOT_FAIL_ON_UNRESOLVED || 'false' }}", + "bugbot-organization-rules": "${{ vars.BUGBOT_ORGANIZATION_RULES }}", + "project-column-issue-created": "${{ vars.PROJECT_COLUMN_ISSUE_CREATED || 'Todo' }}", + "project-column-pull-request-created": "${{ vars.PROJECT_COLUMN_PULL_REQUEST_CREATED || 'In Progress' }}", + "project-column-issue-in-progress": "${{ vars.PROJECT_COLUMN_ISSUE_IN_PROGRESS || 'In Progress' }}", + "project-column-pull-request-in-progress": "${{ vars.PROJECT_COLUMN_PULL_REQUEST_IN_PROGRESS || 'In Progress' }}", + "agent-provider": "${{ vars.AGENT_PROVIDER || 'codex' }}", + "agent-model-provider": "${{ vars.AGENT_MODEL_PROVIDER || 'openai' }}", + "agent-model": "${{ vars.AGENT_MODEL || 'gpt-6-luna' }}", + "agent-effort": "${{ vars.AGENT_EFFORT }}", + "agent-executable": "${{ vars.AGENT_EXECUTABLE }}", + "findings-provider": "${{ vars.FINDINGS_PROVIDER }}", + "findings-model-provider": "${{ vars.FINDINGS_MODEL_PROVIDER }}", + "findings-model": "${{ vars.FINDINGS_MODEL }}", + "findings-effort": "${{ vars.FINDINGS_EFFORT }}", + "findings-executable": "${{ vars.FINDINGS_EXECUTABLE }}", + "fixer-provider": "${{ vars.FIXER_PROVIDER }}", + "fixer-model-provider": "${{ vars.FIXER_MODEL_PROVIDER }}", + "fixer-model": "${{ vars.FIXER_MODEL }}", + "fixer-effort": "${{ vars.FIXER_EFFORT }}", + "fixer-executable": "${{ vars.FIXER_EXECUTABLE }}", + "planner-provider": "${{ vars.PLANNER_PROVIDER }}", + "planner-model-provider": "${{ vars.PLANNER_MODEL_PROVIDER }}", + "planner-model": "${{ vars.PLANNER_MODEL }}", + "planner-effort": "${{ vars.PLANNER_EFFORT }}", + "planner-executable": "${{ vars.PLANNER_EXECUTABLE }}", + "reviewer-provider": "${{ vars.REVIEWER_PROVIDER }}", + "reviewer-model-provider": "${{ vars.REVIEWER_MODEL_PROVIDER }}", + "reviewer-model": "${{ vars.REVIEWER_MODEL }}", + "reviewer-effort": "${{ vars.REVIEWER_EFFORT }}", + "reviewer-executable": "${{ vars.REVIEWER_EXECUTABLE }}", + "tester-provider": "${{ vars.TESTER_PROVIDER }}", + "tester-model-provider": "${{ vars.TESTER_MODEL_PROVIDER }}", + "tester-model": "${{ vars.TESTER_MODEL }}", + "tester-effort": "${{ vars.TESTER_EFFORT }}", + "tester-executable": "${{ vars.TESTER_EXECUTABLE }}", + "project-ids": "${{ vars.PROJECT_IDS }}" +} diff --git a/src/infrastructure/setup_management_workspace_adapter.ts b/src/infrastructure/setup_management_workspace_adapter.ts index 0bf7f2fc3..d14583db1 100644 --- a/src/infrastructure/setup_management_workspace_adapter.ts +++ b/src/infrastructure/setup_management_workspace_adapter.ts @@ -4,6 +4,8 @@ import { createHash } from 'node:crypto'; import { load, JSON_SCHEMA } from 'js-yaml'; import type { SetupInstallation, SetupInstalledWorkflow, SetupInstalledInput } from '../domain/setup_management'; import { redactSensitiveText } from '../domain/security/sensitive_text'; +import { isCopilotCommentWorkflow, COPILOT_COMMENT_SELF_WORKFLOW } from '../domain/copilot_comment_workflow'; +import commentInputs from './copilot_comment_inputs.json'; type Document = Record; type WorkflowStep = { job: Document; step: Document }; @@ -86,12 +88,29 @@ export class SetupManagementWorkspaceAdapter { private inspectWorkflow(file: string, localAction: () => string | undefined): SetupInstalledWorkflow[] { const { source, document } = readDocument(join(this.root, '.github', 'workflows', file)); const steps = workflowSteps(document); + const jobs = Object.values(object(document.jobs)).map(object); + if (jobs.some(job => typeof job.uses === 'string' + && /^(?:vypdev\/copilot\/|[.$]\/)\.github\/workflows\/copilot_comment_runtime\.yml(?:@|$)/iu.test(job.uses) + && !isCopilotCommentWorkflow(job.uses))) throw new Error('Unsupported comment workflow reference.'); + const calls = jobs.filter(job => isCopilotCommentWorkflow(job.uses)); + if (calls.some(job => job.uses === COPILOT_COMMENT_SELF_WORKFLOW) && !localAction()) throw new Error('Unverified source comment workflow.'); + const reusable = calls.map(job => { + const overrides = object(job.with); + if (Object.keys(overrides).some(key => !['runs-on', 'issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files', 'prepare-source-verification'].includes(key))) throw new Error('Unknown comment workflow input.'); + const bindings: Record = { ...commentInputs }; + for (const name of ['issue-managed-branches', 'pre-branch-sdd', 'ai-ignore-files']) { + if (overrides[name] !== undefined && overrides[name] !== '') bindings[name] = overrides[name]; + } + return { file, action: job.uses === COPILOT_COMMENT_SELF_WORKFLOW ? './' : `vypdev/copilot@${String(job.uses).split('@').at(-1)}`, + digest: digest(source), environmentScoped: environmentScoped(document, job, {}), + inputs: Object.entries(bindings).flatMap(([name, value]) => installedInput(name, value)) }; + }); const knownLocalAction = steps.some(({ step }) => step.uses === './') ? Boolean(localAction()) : false; - return steps.flatMap(({ job, step }) => { + return [...reusable, ...steps.flatMap(({ job, step }) => { if (!this.isCopilotStep(step, knownLocalAction)) return []; const inputs = Object.entries(object(step.with)).flatMap(([name, value]) => installedInput(name, value)); return [{ file, action: step.uses as string, digest: digest(source), environmentScoped: environmentScoped(document, job, step), inputs }]; - }); + })]; } private isCopilotStep(step: Document, knownLocalAction: boolean): boolean { diff --git a/src/tooling/__tests__/validate_workflow_contract.test.ts b/src/tooling/__tests__/validate_workflow_contract.test.ts index e050dcb1f..b58e0a72d 100644 --- a/src/tooling/__tests__/validate_workflow_contract.test.ts +++ b/src/tooling/__tests__/validate_workflow_contract.test.ts @@ -154,21 +154,19 @@ describe('workflow contract validator', () => { }); it.each(['issue-managed-branches', 'pre-branch-sdd', 'verification-setup'])( - 'rejects a PR comment callback that omits or disables the installed %s policy', input => { - const { file, workflow } = loadMutationWorkflow('.github/workflows', 'copilot_pull_request_comment.yml'); - const action = workflow.jobs['copilot-pull-requests'].steps.find((step: { id?: string }) => step.id === 'copilot'); + 'rejects a comment coordinator that omits or disables the installed %s policy', input => { + const { file, workflow } = loadMutationWorkflow('.github/workflows', 'copilot_comment_runtime.yml'); + const action = workflow.jobs.copilot.steps.find((step: { id?: string }) => step.id === 'copilot'); delete action.with[input]; - expect(() => assertIssueBranchConfigurationInputs(file, workflow)).toThrow('must pass consistent'); + expect(() => validateWorkflow(file, workflow)).toThrow('native comment runtime'); action.with[input] = false; - expect(() => assertIssueBranchConfigurationInputs(file, workflow)).toThrow('must pass consistent'); + expect(() => validateWorkflow(file, workflow)).toThrow('native comment runtime'); }, ); it('rejects a distributed callback that enables the SDD gate instead of inheriting its configured default', () => { const { file, workflow } = loadMutationWorkflow('setup/workflows', 'copilot_pull_request_comment.yml'); - const action = workflow.jobs['copilot-pull-requests'].steps.find( - (step: { uses?: string }) => step.uses?.startsWith('vypdev/copilot@'), - ); + const action = workflow.jobs['copilot-pull-requests']; action.with['pre-branch-sdd'] = "${{ vars.PRE_BRANCH_SDD || 'true' }}"; expect(() => assertIssueBranchConfigurationInputs(file, workflow)).toThrow('must pass consistent'); }); @@ -193,7 +191,8 @@ describe('workflow contract validator', () => { 'copilot_issue_comment.yml', 'copilot_pull_request.yml', 'copilot_pull_request_comment.yml', 'copilot_pull_request_review_state.yml', ]) { - const workflow = yaml.load(readFileSync(path.join(process.cwd(), directory, fileName), 'utf8')) as MutationWorkflow; + const coordinator = ['copilot_issue_comment.yml', 'copilot_pull_request_comment.yml'].includes(fileName); + const workflow = yaml.load(readFileSync(path.join(process.cwd(), coordinator ? '.github/workflows' : directory, coordinator ? 'copilot_comment_runtime.yml' : fileName), 'utf8')) as MutationWorkflow; const steps = Object.values(workflow.jobs).flatMap(job => job.steps ?? []); const modelInputs = steps.filter(step => step.with?.['agent-model']); expect(modelInputs).not.toHaveLength(0); @@ -1634,7 +1633,7 @@ describe('workflow contract validator', () => { const file = path.join(process.cwd(), 'setup/workflows/copilot_issue_comment.yml'); const workflow = yaml.load(readFileSync(file, 'utf8')) as MutationWorkflow; - workflow.jobs['copilot-issues'].steps.splice(1, 0, { uses: 'actions/setup-node@v7' }); + workflow.jobs['copilot-issues'].steps = [{ uses: 'actions/setup-node@v7' }]; expect(() => assertAgentInstallationPrerequisites(file, workflow)).toThrow('standalone official agent installation'); }); @@ -1685,11 +1684,13 @@ describe('workflow contract validator', () => { job.permissions = { contents: 'read' }; expect(() => assertAgentWorkflowPermissions(file, workflow)).toThrow('must grant GITHUB_TOKEN exactly'); job.permissions = { checks: 'write', contents: 'read' }; - const action = job.steps.find((step: any) => step.env?.COPILOT_EVIDENCE_TOKEN); + const central = loadMutationWorkflow('.github/workflows', 'copilot_comment_runtime.yml'); + const runtime = central.workflow.jobs.copilot; + const action = runtime.steps.find((step: any) => step.env?.COPILOT_EVIDENCE_TOKEN); delete action.env.COPILOT_EVIDENCE_TOKEN; - expect(() => assertAgentWorkflowPermissions(file, workflow)).toThrow('must scope COPILOT_EVIDENCE_TOKEN'); - job.steps.push({ run: 'true', env: { COPILOT_EVIDENCE_TOKEN: '${{ github.token }}' } }); - expect(() => assertAgentWorkflowPermissions(file, workflow)).toThrow('must scope COPILOT_EVIDENCE_TOKEN'); + expect(() => assertAgentWorkflowPermissions(central.file, central.workflow)).toThrow('must scope COPILOT_EVIDENCE_TOKEN'); + runtime.steps.push({ run: 'true', env: { COPILOT_EVIDENCE_TOKEN: '${{ github.token }}' } }); + expect(() => assertAgentWorkflowPermissions(central.file, central.workflow)).toThrow('must scope COPILOT_EVIDENCE_TOKEN'); } }, ); diff --git a/src/tooling/__tests__/verification_runtime_guidance.test.ts b/src/tooling/__tests__/verification_runtime_guidance.test.ts index d7231b2f0..87e3136b3 100644 --- a/src/tooling/__tests__/verification_runtime_guidance.test.ts +++ b/src/tooling/__tests__/verification_runtime_guidance.test.ts @@ -8,10 +8,12 @@ describe('shipped verification runtime guidance', () => { const content = readFileSync(path.resolve('setup/workflows', `${name}.yml`), 'utf8'); expect(content).toContain('.copilot/verification-prerequisites.json'); expect(content).toContain('#repository-verification-prerequisites'); - const workflow = yaml.load(content) as { jobs: Record }> }; - const actions = Object.values(workflow.jobs).flatMap(job => job.steps.map(step => step.uses)); + const workflow = yaml.load(content) as { jobs: Record }> }; + const actions = Object.values(workflow.jobs).flatMap(job => [job.uses, ...(job.steps ?? []).map(step => step.uses)]); expect(actions).not.toContain('actions/setup-java@v5'); - expect(actions).toContain('vypdev/copilot@v3'); + expect(actions).toContain(name.endsWith('_comment') + ? 'vypdev/copilot/.github/workflows/copilot_comment_runtime.yml@v3' + : 'vypdev/copilot@v3'); } }); }); diff --git a/src/utils/__tests__/setup_runner_installation.test.ts b/src/utils/__tests__/setup_runner_installation.test.ts index b0e1831aa..fd44f6820 100644 --- a/src/utils/__tests__/setup_runner_installation.test.ts +++ b/src/utils/__tests__/setup_runner_installation.test.ts @@ -60,6 +60,16 @@ describe('installation parity and reviewed migration', () => { const write = (path: string, content: string) => { const absolute = join(root, path); mkdirSync(dirname(absolute), { recursive: true }); writeFileSync(absolute, content); }; beforeEach(() => { root = mkdtempSync(join(tmpdir(), 'copilot-runner-parity-')); }); afterEach(() => rmSync(root, { recursive: true, force: true })); + test('reviews and applies the same retained runner for compact reusable comment jobs', () => { + const legacy = single('[self-hosted, reviewed, Linux]').replace('run: echo fixture', 'uses: vypdev/copilot@v3'); + write('.github/workflows/copilot_issue_comment.yml', legacy); + const config = { ...createDefaultSetupConfiguration(), runners: selectSetupRunnerMode('retain') }; + const review = inspectSetupInstallation(root, config); + expect(review.jobs.find(job => job.file === 'copilot_issue_comment.yml')).toMatchObject({ role: 'agent', runsOn: ['self-hosted', 'reviewed', 'Linux'], retained: true }); + const expected = review.changes.find(change => change.path === '.github/workflows/copilot_issue_comment.yml')!.after; + copySetupFiles(root, undefined, config.features, { setupConfiguration: config, updateExistingWorkflows: true, approvedWorkflowFiles: ['copilot_issue_comment.yml'] }); + expect(readFileSync(join(root, '.github/workflows/copilot_issue_comment.yml'), 'utf8')).toBe(expected); + }); test('an incomplete template package still inventories native YAML files without inventing managed assets', () => { const setup = join(root, 'empty-setup'); mkdirSync(setup); write('.github/workflows/native.yaml', workflow(' native:\n runs-on: ubuntu-latest\n')); diff --git a/src/utils/__tests__/setup_workflow_upgrade.test.ts b/src/utils/__tests__/setup_workflow_upgrade.test.ts index cbda42001..53f88cda1 100644 --- a/src/utils/__tests__/setup_workflow_upgrade.test.ts +++ b/src/utils/__tests__/setup_workflow_upgrade.test.ts @@ -1,8 +1,51 @@ import { dump, load } from 'js-yaml'; import { hasRootLocalSetupAction, renderSetupWorkflowUpgrade } from '../setup_workflow_upgrade'; +import { copilotCommentRunner, COPILOT_COMMENT_REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW } from '../../domain/copilot_comment_workflow'; const workflow = (runner: unknown, extra = '') => `name: Reviewed workflow\non: [pull_request]\njobs:\n copilot:\n${dump({ 'runs-on': runner }).trimEnd().split('\n').map(line => ` ${line}`).join('\n')}\n${extra} steps:\n - run: echo reviewed\n`; const selected = (content: string) => (load(content) as { jobs: { copilot: { 'runs-on': unknown } } }).jobs.copilot['runs-on']; +const comment = (route: unknown = 'ubuntu-latest') => dump({ on: { issue_comment: { types: ['created', 'edited'] } }, jobs: { copilot: { + uses: COPILOT_COMMENT_REMOTE_WORKFLOW, with: { 'runs-on': JSON.stringify(route) }, secrets: { PAT: '${{ secrets.PAT }}' }, +} } }); + +describe('comment workflow coordination upgrade', () => { + it.each(['ubuntu-latest', ['self-hosted', 'codex', 'Linux'], { group: 'trusted', labels: ['self-hosted', 'Linux'] }])('migrates the reviewed native runner %j and stays idempotent', route => { + const previous = workflow(route).replace('run: echo reviewed', 'uses: vypdev/copilot@v3'); + const result = renderSetupWorkflowUpgrade(comment(), previous); + const parsed = load(result) as any; + expect(copilotCommentRunner(parsed.jobs.copilot)).toEqual(route); + expect(parsed.jobs.copilot.steps).toBeUndefined(); + expect(renderSetupWorkflowUpgrade(comment(), result)).toBe(result); + }); + it('retains a previously upgraded group route', () => { + expect(copilotCommentRunner((load(renderSetupWorkflowUpgrade(comment(), comment({ group: 'trusted', labels: ['self-hosted', 'Linux'] }))) as any).jobs.copilot)) + .toEqual({ group: 'trusted', labels: ['self-hosted', 'Linux'] }); + }); + it('uses an explicitly selected runner profile instead of the prior route', () => { + const template = comment().replace(' copilot:', ' copilot-issues:'); + const result = renderSetupWorkflowUpgrade(template, undefined, { file: 'copilot_issue_comment.yml', runners: { + mode: 'manual-self-hosted', profileId: '', group: 'trusted', labels: ['self-hosted', 'Linux'], validation: 'hosted', + } }); + expect(copilotCommentRunner((load(result) as any).jobs['copilot-issues'])).toEqual({ group: 'trusted', labels: ['self-hosted', 'Linux'] }); + }); + it('preserves source-only self-repository coordination exactly', () => { + const source = comment().replace(COPILOT_COMMENT_REMOTE_WORKFLOW, COPILOT_COMMENT_SELF_WORKFLOW); + expect(hasRootLocalSetupAction(source)).toBe(true); + expect(renderSetupWorkflowUpgrade(comment(), source)).toBe(source); + }); + it.each(['actions/setup-node@v7', 'actions/setup-java@v5'])('blocks silently dropping custom bootstrap %s', uses => { + expect(() => renderSetupWorkflowUpgrade(comment(), workflow('ubuntu-latest').replace('run: echo reviewed', `uses: ${uses}`))).toThrow('migration'); + }); + it('blocks custom shell steps during migration', () => { + expect(() => renderSetupWorkflowUpgrade(comment(), workflow('ubuntu-latest'))).toThrow('migration'); + }); + it('blocks malformed reusable runner JSON', () => { + expect(() => renderSetupWorkflowUpgrade(comment(), comment().replace('"ubuntu-latest"', 'invalid'))).toThrow('review'); + }); + it('blocks dynamic native runners instead of transplanting their missing matrix', () => { + expect(() => renderSetupWorkflowUpgrade(comment(), workflow('${{ matrix.os }}').replace('run: echo reviewed', 'uses: vypdev/copilot@v3'))).toThrow('Dynamic'); + }); +}); describe('setup retains reviewed target workflow runners', () => { it('retains source Action jobs, permissions and release customizations instead of consumer templates', () => { diff --git a/src/utils/setup_installation_review.ts b/src/utils/setup_installation_review.ts index 46d5f5064..925004614 100644 --- a/src/utils/setup_installation_review.ts +++ b/src/utils/setup_installation_review.ts @@ -14,6 +14,7 @@ import { REPOSITORY_AGENT_GUIDE_PATH, REPOSITORY_AGENT_PROFILE_PATH, REPOSITORY_ REPOSITORY_AGENT_SKILL_PATH } from '../application/policies/repository_agent_guidance_policy'; import { SETUP_VERIFICATION_ACTION_PATH, type SetupVerificationActionReview } from '../domain/setup_verification_action'; import { inspectSetupVerificationActionPath, readSetupVerificationActionStarter } from '../infrastructure/setup_verification_action'; +import { copilotCommentRunner } from '../domain/copilot_comment_workflow'; export const SETUP_RUNNER_SNAPSHOT = '.copilot/runner-profile.json'; const object = (value: unknown): Record | undefined => value !== null && typeof value === 'object' && !Array.isArray(value) @@ -68,7 +69,7 @@ export function inspectSetupInstallation(root: string, configuration: SetupConfi const parsedJobs = object(object(documents[0])?.jobs); if (!parsedJobs) throw new Error('Workflow jobs are unavailable for review.'); for (const [job, raw] of Object.entries(parsedJobs)) { - const runsOn = object(raw)?.['runs-on']; + const runsOn = copilotCommentRunner(object(raw)); if (runsOn === undefined) continue; // reusable workflow calls have no runner jobs.push({ file, job, role: setupRunnerRole(file, job) ?? 'validation', runsOn: runsOn as SetupInstallationReview['jobs'][number]['runsOn'], status: 'access-unknown', retained }); diff --git a/src/utils/setup_workflow_upgrade.ts b/src/utils/setup_workflow_upgrade.ts index cdf4c869d..44a2e1e5e 100644 --- a/src/utils/setup_workflow_upgrade.ts +++ b/src/utils/setup_workflow_upgrade.ts @@ -3,6 +3,7 @@ import { isDeepStrictEqual } from 'node:util'; import type { SetupRunnerConfiguration } from '../domain/setup_runner'; import { selectedSetupRunsOn, setupRunnerRole, validateSetupRunners } from '../application/policies/setup_runner_policy'; import { ACTIONS } from '../data/model/action_types'; +import { copilotCommentRunner, COPILOT_COMMENT_SELF_WORKFLOW, isCopilotCommentWorkflow } from '../domain/copilot_comment_workflow'; const object = (value: unknown): Record | undefined => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record : undefined; @@ -23,6 +24,7 @@ const runner = (value: unknown): boolean => labels(value) || !!object(value) && (object(value)!.labels === undefined || labels(object(value)!.labels)); const copilotCommands = new Set(Object.values(ACTIONS)); const callsRootAction = (jobs: Record | undefined): boolean => !!jobs && Object.values(jobs).some(job => { + if (object(job)?.uses === COPILOT_COMMENT_SELF_WORKFLOW) return true; const steps = object(job)?.steps; return Array.isArray(steps) && steps.some(step => { const invocation = object(step); const inputs = object(invocation?.with); @@ -82,6 +84,28 @@ export function renderSetupWorkflowUpgrade(template: string, existing?: string, } const templateJobs = object(document(template)?.jobs); if (!previousJobs || !templateJobs) throw new Error('Workflow jobs cannot be inspected; review the workflow separately.'); + if (Object.values(templateJobs).some(job => isCopilotCommentWorkflow(object(job)?.uses))) { + const parsed = document(template)!; + const jobs = object(parsed.jobs)!; + let changed = false; + for (const [name, value] of Object.entries(jobs)) { + const job = object(value)!; + if (!isCopilotCommentWorkflow(job.uses)) throw new Error('Mixed comment workflow jobs require separate workflow review before setup.'); + const previousJob = object(previousJobs[name]); + if (Array.isArray(previousJob?.steps) && previousJob.steps.some(raw => { + const uses = object(raw)?.uses; + return typeof uses !== 'string' || !(uses.startsWith('actions/checkout@') + || /^vypdev\/copilot@[^\s]+$/u.test(uses) || uses === './.git/copilot-verification-setup'); + })) throw new Error('Custom comment job steps require migration to the reviewed repository verification setup action before switching to the reusable workflow. Review the workflow separately.'); + const retained = selectedSetupRunsOn(selection?.runners, selection && setupRunnerRole(selection.file, name)) + ?? copilotCommentRunner(previousJob) ?? copilotCommentRunner(job); + if (!runner(retained)) throw new Error('Existing runner selection is invalid; review the workflow separately.'); + if (JSON.stringify(retained).includes('${{') && existing !== template) throw new Error('Dynamic runner selection requires separate workflow review before setup.'); + changed ||= !isDeepStrictEqual(retained, copilotCommentRunner(job)); + job.with = { ...object(job.with), 'runs-on': JSON.stringify(retained) }; + } + return changed ? dump(parsed, { noRefs: true, lineWidth: -1 }) : template; + } const lines = template.split('\n'); let job = ''; let insideJobs = false;