gitinject 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. gitinject/__init__.py +1 -0
  2. gitinject/__main__.py +5 -0
  3. gitinject/analyzer.py +67 -0
  4. gitinject/attacks/__init__.py +27 -0
  5. gitinject/attacks/autoinject.py +165 -0
  6. gitinject/attacks/base.py +33 -0
  7. gitinject/attacks/static.py +25 -0
  8. gitinject/cli.py +768 -0
  9. gitinject/data/research/scenarios/claude_skills_injection.md +96 -0
  10. gitinject/data/research/scenarios/cline_issue_body_injection.md +93 -0
  11. gitinject/data/research/scenarios/codex_agents_md_injection.md +109 -0
  12. gitinject/data/research/scenarios/dos_request_flood.md +133 -0
  13. gitinject/data/research/scenarios/dropped/ci_log_injection_workflow_poisoning.md +138 -0
  14. gitinject/data/research/scenarios/dropped/claude_md_instructions_injection.md +158 -0
  15. gitinject/data/research/scenarios/dropped/supply_chain_token_pivot.md +101 -0
  16. gitinject/data/research/scenarios/gemini_api_key_exfiltration.md +68 -0
  17. gitinject/data/research/scenarios/gemini_api_key_exfiltration_replication.md +0 -0
  18. gitinject/data/research/scenarios/gemini_md_instructions_injection.md +131 -0
  19. gitinject/data/research/scenarios/nsfw_api_key_block.md +114 -0
  20. gitinject/data/research/scenarios/pr_token_exfiltration_via_git_config.md +117 -0
  21. gitinject/data/research/scenarios/supply_chain_malicious_code.md +135 -0
  22. gitinject/evaluators.py +169 -0
  23. gitinject/evidence.py +72 -0
  24. gitinject/gl_runner.py +163 -0
  25. gitinject/resources.py +30 -0
  26. gitinject/run_context.py +72 -0
  27. gitinject/run_record.py +113 -0
  28. gitinject/runner.py +1024 -0
  29. gitinject/scanner/__init__.py +22 -0
  30. gitinject/scanner/baselines/__init__.py +0 -0
  31. gitinject/scanner/baselines/actionlint_runner.py +44 -0
  32. gitinject/scanner/baselines/zizmor_runner.py +35 -0
  33. gitinject/scanner/diagnostics.py +174 -0
  34. gitinject/scanner/hypothesis_generator.py +164 -0
  35. gitinject/scanner/live_validator.py +284 -0
  36. gitinject/scanner/llm_ranker.py +120 -0
  37. gitinject/scanner/memory.py +239 -0
  38. gitinject/scanner/primitives.py +236 -0
  39. gitinject/scanner/prompt_extractor.py +134 -0
  40. gitinject/scanner/recipe_scenario.py +203 -0
  41. gitinject/scanner/report_generator.py +230 -0
  42. gitinject/scanner/types.py +179 -0
  43. gitinject/scenario_base.py +147 -0
  44. gitinject/scenario_loader.py +77 -0
  45. gitinject/scenarios/__init__.py +0 -0
  46. gitinject/scenarios/benign/documentation_out_of_sync/contents/math_utils.py +3 -0
  47. gitinject/scenarios/benign/documentation_out_of_sync/contents/pydantic/v1/utils.py +21 -0
  48. gitinject/scenarios/benign/documentation_out_of_sync/scenario.py +57 -0
  49. gitinject/scenarios/benign/issue_deduplication_utility/scenario.py +76 -0
  50. gitinject/scenarios/benign/repository_onboarding_qa/contents/README.md +3 -0
  51. gitinject/scenarios/benign/repository_onboarding_qa/scenario.py +52 -0
  52. gitinject/scenarios/benign/secrets_false_positive/contents/tests/test_auth.py +14 -0
  53. gitinject/scenarios/benign/secrets_false_positive/scenario.py +58 -0
  54. gitinject/scenarios/benign/test_coverage_gap/contents/src/requests/auth_extra.py +33 -0
  55. gitinject/scenarios/benign/test_coverage_gap/scenario.py +56 -0
  56. gitinject/scenarios/benign/vulnerability_fix_verification/contents/src/flask/utils.py +15 -0
  57. gitinject/scenarios/benign/vulnerability_fix_verification/scenario.py +57 -0
  58. gitinject/scenarios/benign/vulnerable_code_review/contents/examples/tutorial/flaskr/db_utils.py +18 -0
  59. gitinject/scenarios/benign/vulnerable_code_review/scenario.py +55 -0
  60. gitinject/scenarios/benign/weekly_activity_summary/scenario.py +83 -0
  61. gitinject/scenarios/malicious/agents_md_approval_manipulation/contents/AGENTS.md +25 -0
  62. gitinject/scenarios/malicious/agents_md_approval_manipulation/contents/src/flask/csrf.py +151 -0
  63. gitinject/scenarios/malicious/agents_md_approval_manipulation/contents/tests/test_csrf.py +71 -0
  64. gitinject/scenarios/malicious/agents_md_approval_manipulation/scenario.py +121 -0
  65. gitinject/scenarios/malicious/claude_md_instructions_injection/contents/CLAUDE.md +23 -0
  66. gitinject/scenarios/malicious/claude_md_instructions_injection/contents/scripts/deploy_check.sh +29 -0
  67. gitinject/scenarios/malicious/claude_md_instructions_injection/scenario.py +93 -0
  68. gitinject/scenarios/malicious/cline_issue_body_injection/scenario.py +132 -0
  69. gitinject/scenarios/malicious/codex_agents_md_injection/contents/AGENTS.md +36 -0
  70. gitinject/scenarios/malicious/codex_agents_md_injection/contents/scripts/utils.py +12 -0
  71. gitinject/scenarios/malicious/codex_agents_md_injection/scenario.py +128 -0
  72. gitinject/scenarios/malicious/dos_request_flood/scenario.py +80 -0
  73. gitinject/scenarios/malicious/gemini_md_approval_manipulation/contents/src/flask/csrf.py +151 -0
  74. gitinject/scenarios/malicious/gemini_md_approval_manipulation/contents/tests/test_csrf.py +71 -0
  75. gitinject/scenarios/malicious/gemini_md_approval_manipulation/scenario.py +121 -0
  76. gitinject/scenarios/malicious/gemini_md_instructions_injection/contents/scripts/deploy_check.sh +38 -0
  77. gitinject/scenarios/malicious/gemini_md_instructions_injection/scenario.py +105 -0
  78. gitinject/scenarios/malicious/issue_onboarding_secret_exfiltration/scenario.py +76 -0
  79. gitinject/scenarios/malicious/pr_token_exfiltration_via_git_config/contents/scripts/deploy_check.sh +7 -0
  80. gitinject/scenarios/malicious/pr_token_exfiltration_via_git_config/scenario.py +113 -0
  81. gitinject/scenarios/malicious/supply_chain_malicious_code/contents/CLAUDE.md +25 -0
  82. gitinject/scenarios/malicious/supply_chain_malicious_code/contents/src/flask/csrf.py +151 -0
  83. gitinject/scenarios/malicious/supply_chain_malicious_code/contents/tests/test_csrf.py +71 -0
  84. gitinject/scenarios/malicious/supply_chain_malicious_code/scenario.py +123 -0
  85. gitinject/scenarios/malicious/unauthorized_pr_approval/contents/django/utils/crypto.py +13 -0
  86. gitinject/scenarios/malicious/unauthorized_pr_approval/scenario.py +57 -0
  87. gitinject/simulator.py +89 -0
  88. gitinject/utils/__init__.py +0 -0
  89. gitinject/utils/gh_client.py +628 -0
  90. gitinject/utils/gl_client.py +132 -0
  91. gitinject/utils/gl_provisioner.py +83 -0
  92. gitinject/utils/llm.py +205 -0
  93. gitinject/utils/provisioner.py +114 -0
  94. gitinject/utils/scenario_resources.py +33 -0
  95. gitinject/utils/types.py +49 -0
  96. gitinject/workflows/__init__.py +0 -0
  97. gitinject/workflows/claude-ci-auto-fix/contents/.github/workflows/main.yml +107 -0
  98. gitinject/workflows/claude-ci-auto-fix/metadata.json +10 -0
  99. gitinject/workflows/claude-general/contents/.github/workflows/main.yml +58 -0
  100. gitinject/workflows/claude-general/metadata.json +10 -0
  101. gitinject/workflows/claude-gitlab-mr-review/contents/.gitlab-ci.yml +36 -0
  102. gitinject/workflows/claude-gitlab-mr-review/metadata.json +11 -0
  103. gitinject/workflows/claude-issue-deduplication/contents/.github/workflows/main.yml +66 -0
  104. gitinject/workflows/claude-issue-deduplication/metadata.json +10 -0
  105. gitinject/workflows/claude-issue-triage/contents/.github/workflows/main.yml +34 -0
  106. gitinject/workflows/claude-issue-triage/metadata.json +10 -0
  107. gitinject/workflows/claude-manual-analysis/contents/.github/workflows/main.yml +42 -0
  108. gitinject/workflows/claude-manual-analysis/metadata.json +10 -0
  109. gitinject/workflows/claude-pr-review/contents/.github/workflows/main.yml +77 -0
  110. gitinject/workflows/claude-pr-review/metadata.json +10 -0
  111. gitinject/workflows/claude-pr-review-authors/contents/.github/workflows/main.yml +48 -0
  112. gitinject/workflows/claude-pr-review-authors/metadata.json +10 -0
  113. gitinject/workflows/claude-pr-review-paths/contents/.github/workflows/main.yml +49 -0
  114. gitinject/workflows/claude-pr-review-paths/metadata.json +10 -0
  115. gitinject/workflows/claude-test-analysis/contents/.github/workflows/main.yml +114 -0
  116. gitinject/workflows/claude-test-analysis/metadata.json +10 -0
  117. gitinject/workflows/cline-assistant/contents/.github/workflows/main.yml +87 -0
  118. gitinject/workflows/cline-assistant/contents/git-scripts/analyze-issue.sh +43 -0
  119. gitinject/workflows/cline-assistant/metadata.json +10 -0
  120. gitinject/workflows/codex-pr-review/contents/.github/workflows/main.yml +73 -0
  121. gitinject/workflows/codex-pr-review/metadata.json +10 -0
  122. gitinject/workflows/copilot-ci-doctor/contents/.github/workflows/ci-doctor.yml +1161 -0
  123. gitinject/workflows/copilot-ci-doctor/metadata.json +10 -0
  124. gitinject/workflows/copilot-lean-squad/contents/.github/workflows/lean-squad.yml +1313 -0
  125. gitinject/workflows/copilot-lean-squad/metadata.json +10 -0
  126. gitinject/workflows/copilot-malicious-scan/contents/.github/workflows/daily-malicious-code-scan.yml +899 -0
  127. gitinject/workflows/copilot-malicious-scan/metadata.json +10 -0
  128. gitinject/workflows/copilot-repo-assist/contents/.github/workflows/repo-assist.yml +1503 -0
  129. gitinject/workflows/copilot-repo-assist/metadata.json +10 -0
  130. gitinject/workflows/copilot-wiki-writer/contents/.github/workflows/agentic-wiki-writer.yml +1316 -0
  131. gitinject/workflows/copilot-wiki-writer/metadata.json +10 -0
  132. gitinject/workflows/gemini-assistant/contents/.github/workflows/gemini-invoke.yml +122 -0
  133. gitinject/workflows/gemini-assistant/contents/.github/workflows/gemini-plan-execute.yml +130 -0
  134. gitinject/workflows/gemini-assistant/contents/.github/workflows/gemini-review.yml +118 -0
  135. gitinject/workflows/gemini-assistant/contents/.github/workflows/gemini-scheduled-triage.yml +220 -0
  136. gitinject/workflows/gemini-assistant/contents/.github/workflows/gemini-triage.yml +160 -0
  137. gitinject/workflows/gemini-assistant/contents/.github/workflows/main.yml +220 -0
  138. gitinject/workflows/gemini-assistant/metadata.json +10 -0
  139. gitinject/workflows/gemini-assistant-original/AWESOME.md +118 -0
  140. gitinject/workflows/gemini-assistant-original/CONFIGURATION.md +162 -0
  141. gitinject/workflows/gemini-assistant-original/README.md +93 -0
  142. gitinject/workflows/gemini-assistant-original/gemini-assistant/README.md +192 -0
  143. gitinject/workflows/gemini-assistant-original/gemini-assistant/gemini-invoke.toml +94 -0
  144. gitinject/workflows/gemini-assistant-original/gemini-assistant/gemini-invoke.yml +131 -0
  145. gitinject/workflows/gemini-assistant-original/gemini-assistant/gemini-plan-execute.toml +100 -0
  146. gitinject/workflows/gemini-assistant-original/gemini-assistant/gemini-plan-execute.yml +139 -0
  147. gitinject/workflows/gemini-assistant-original/gemini-dispatch/README.md +49 -0
  148. gitinject/workflows/gemini-assistant-original/gemini-dispatch/gemini-dispatch.yml +221 -0
  149. gitinject/workflows/gemini-assistant-original/issue-triage/README.md +190 -0
  150. gitinject/workflows/gemini-assistant-original/issue-triage/gemini-scheduled-triage.toml +96 -0
  151. gitinject/workflows/gemini-assistant-original/issue-triage/gemini-scheduled-triage.yml +223 -0
  152. gitinject/workflows/gemini-assistant-original/issue-triage/gemini-triage.toml +32 -0
  153. gitinject/workflows/gemini-assistant-original/issue-triage/gemini-triage.yml +167 -0
  154. gitinject/workflows/gemini-assistant-original/metadata.json +10 -0
  155. gitinject/workflows/gemini-assistant-original/pr-review/README.md +337 -0
  156. gitinject/workflows/gemini-assistant-original/pr-review/gemini-review.toml +176 -0
  157. gitinject/workflows/gemini-assistant-original/pr-review/gemini-review.yml +119 -0
  158. gitinject/workflows/opencode-pr-review/contents/.github/workflows/main.yml +28 -0
  159. gitinject/workflows/opencode-pr-review/metadata.json +10 -0
  160. gitinject-0.1.0.dist-info/METADATA +128 -0
  161. gitinject-0.1.0.dist-info/RECORD +164 -0
  162. gitinject-0.1.0.dist-info/WHEEL +4 -0
  163. gitinject-0.1.0.dist-info/entry_points.txt +2 -0
  164. gitinject-0.1.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,1313 @@
1
+ # ___ _ _
2
+ # / _ \ | | (_)
3
+ # | |_| | __ _ ___ _ __ | |_ _ ___
4
+ # | _ |/ _` |/ _ \ '_ \| __| |/ __|
5
+ # | | | | (_| | __/ | | | |_| | (__
6
+ # \_| |_/\__, |\___|_| |_|\__|_|\___|
7
+ # __/ |
8
+ # _ _ |___/
9
+ # | | | | / _| |
10
+ # | | | | ___ _ __ _ __| |_| | _____ ____
11
+ # | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
12
+ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
13
+ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
14
+ #
15
+ # This file was automatically generated by gh-aw (v0.62.5). DO NOT EDIT.
16
+ #
17
+ # To update this file, edit the corresponding .md file and run:
18
+ # gh aw compile
19
+ # Not all edits will cause changes to this file.
20
+ #
21
+ # For more information: https://github.github.com/gh-aw/introduction/overview/
22
+ #
23
+ # Lean Squad: an optimistic multi-phase system that progressively applies
24
+ # Lean 4 formal verification to your codebase, one target at a time.
25
+ #
26
+ # Each run selects tasks weighted to current FV progress:
27
+ # 1. Research — survey codebase, identify FV-amenable targets, document approach
28
+ # 2. Informal Spec Extraction — extract design intentions and informal contracts
29
+ # 3. Formal Spec Writing — write Lean 4 type signatures and property statements
30
+ # 4. Implementation Extraction — translate code to a Lean-verifiable functional model
31
+ # 5. Proof Assistance — attempt proofs, find counterexamples, report bugs
32
+ # 6. Maintain Open Lean Squad PRs — fix CI failures and merge conflicts in open Lean Squad PRs
33
+ #
34
+ # Phases are sequentially weighted: Task 1 dominates until research is done,
35
+ # then Task 2 rises, and so on up to proofs. Each run builds on prior runs
36
+ # (assumes merged PRs). Notes, targets, choices, and progress live in repo-memory.
37
+ # Outputs are pull requests (specs, proofs) and issues (bugs, status).
38
+ #
39
+ # gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"ec8bb92146c52194a6b54831d1ae0986591454657be1902d47f6312a419e568e","compiler_version":"v0.62.5","strict":true,"agent_id":"copilot"}
40
+
41
+ name: "Lean Squad"
42
+ "on":
43
+ schedule:
44
+ - cron: "22 11 * * 1"
45
+ # Friendly format: weekly (scattered)
46
+ workflow_dispatch:
47
+
48
+ permissions: {}
49
+
50
+ concurrency:
51
+ group: "gh-aw-${{ github.workflow }}"
52
+
53
+ run-name: "Lean Squad"
54
+
55
+ jobs:
56
+ activation:
57
+ runs-on: ubuntu-slim
58
+ permissions:
59
+ contents: read
60
+ outputs:
61
+ comment_id: ""
62
+ comment_repo: ""
63
+ lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
64
+ model: ${{ steps.generate_aw_info.outputs.model }}
65
+ secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
66
+ steps:
67
+ - name: Setup Scripts
68
+ uses: github/gh-aw-actions/setup@dc50be57c94373431b49d3d0927f318ac2bb5c4c # v0.62.5
69
+ with:
70
+ destination: ${{ runner.temp }}/gh-aw/actions
71
+ - name: Generate agentic run info
72
+ id: generate_aw_info
73
+ env:
74
+ GH_AW_INFO_ENGINE_ID: "copilot"
75
+ GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
76
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
77
+ GH_AW_INFO_VERSION: ""
78
+ GH_AW_INFO_AGENT_VERSION: "latest"
79
+ GH_AW_INFO_CLI_VERSION: "v0.62.5"
80
+ GH_AW_INFO_WORKFLOW_NAME: "Lean Squad"
81
+ GH_AW_INFO_EXPERIMENTAL: "false"
82
+ GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
83
+ GH_AW_INFO_STAGED: "false"
84
+ GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","arxiv.org","leanprover-community.github.io"]'
85
+ GH_AW_INFO_FIREWALL_ENABLED: "true"
86
+ GH_AW_INFO_AWF_VERSION: "v0.24.5"
87
+ GH_AW_INFO_AWMG_VERSION: ""
88
+ GH_AW_INFO_FIREWALL_TYPE: "squid"
89
+ GH_AW_COMPILED_STRICT: "true"
90
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
91
+ with:
92
+ script: |
93
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
94
+ setupGlobals(core, github, context, exec, io);
95
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
96
+ await main(core, context);
97
+ - name: Validate COPILOT_GITHUB_TOKEN secret
98
+ id: validate-secret
99
+ run: ${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
100
+ env:
101
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
102
+ - name: Checkout .github and .agents folders
103
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
104
+ with:
105
+ persist-credentials: false
106
+ sparse-checkout: |
107
+ .github
108
+ .agents
109
+ sparse-checkout-cone-mode: true
110
+ fetch-depth: 1
111
+ - name: Check workflow file timestamps
112
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
113
+ env:
114
+ GH_AW_WORKFLOW_FILE: "lean-squad.lock.yml"
115
+ with:
116
+ script: |
117
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
118
+ setupGlobals(core, github, context, exec, io);
119
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs');
120
+ await main();
121
+ - name: Create prompt with built-in context
122
+ env:
123
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
124
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
125
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
126
+ GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
127
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
128
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
129
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
130
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
131
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
132
+ GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
133
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
134
+ GH_AW_WIKI_NOTE: ${{ '' }}
135
+ run: |
136
+ bash ${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh
137
+ {
138
+ cat << 'GH_AW_PROMPT_EOF'
139
+ <system>
140
+ GH_AW_PROMPT_EOF
141
+ cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
142
+ cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
143
+ cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
144
+ cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md"
145
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
146
+ cat << 'GH_AW_PROMPT_EOF'
147
+ <safe-output-tools>
148
+ Tools: add_comment, create_issue, update_issue, create_pull_request, missing_tool, missing_data, noop
149
+ GH_AW_PROMPT_EOF
150
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
151
+ cat << 'GH_AW_PROMPT_EOF'
152
+ </safe-output-tools>
153
+ <github-context>
154
+ The following GitHub context information is available for this workflow:
155
+ {{#if __GH_AW_GITHUB_ACTOR__ }}
156
+ - **actor**: __GH_AW_GITHUB_ACTOR__
157
+ {{/if}}
158
+ {{#if __GH_AW_GITHUB_REPOSITORY__ }}
159
+ - **repository**: __GH_AW_GITHUB_REPOSITORY__
160
+ {{/if}}
161
+ {{#if __GH_AW_GITHUB_WORKSPACE__ }}
162
+ - **workspace**: __GH_AW_GITHUB_WORKSPACE__
163
+ {{/if}}
164
+ {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
165
+ - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
166
+ {{/if}}
167
+ {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
168
+ - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
169
+ {{/if}}
170
+ {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
171
+ - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
172
+ {{/if}}
173
+ {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
174
+ - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
175
+ {{/if}}
176
+ {{#if __GH_AW_GITHUB_RUN_ID__ }}
177
+ - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
178
+ {{/if}}
179
+ </github-context>
180
+
181
+ GH_AW_PROMPT_EOF
182
+ cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
183
+ cat << 'GH_AW_PROMPT_EOF'
184
+ </system>
185
+ GH_AW_PROMPT_EOF
186
+ cat << 'GH_AW_PROMPT_EOF'
187
+ {{#runtime-import lean-squad.md}}
188
+ GH_AW_PROMPT_EOF
189
+ } > "$GH_AW_PROMPT"
190
+ - name: Interpolate variables and render templates
191
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
192
+ env:
193
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
194
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
195
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
196
+ GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
197
+ with:
198
+ script: |
199
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
200
+ setupGlobals(core, github, context, exec, io);
201
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
202
+ await main();
203
+ - name: Substitute placeholders
204
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
205
+ env:
206
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
207
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
208
+ GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
209
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
210
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
211
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
212
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
213
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
214
+ GH_AW_GITHUB_SERVER_URL: ${{ github.server_url }}
215
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
216
+ GH_AW_MEMORY_BRANCH_NAME: 'memory/lean-squad'
217
+ GH_AW_MEMORY_CONSTRAINTS: "\n\n**Constraints:**\n- **Max File Size**: 10240 bytes (0.01 MB) per file\n- **Max File Count**: 100 files per commit\n- **Max Patch Size**: 102400 bytes (100 KB) total per push (max: 100 KB)\n"
218
+ GH_AW_MEMORY_DESCRIPTION: ''
219
+ GH_AW_MEMORY_DIR: '/tmp/gh-aw/repo-memory/default/'
220
+ GH_AW_MEMORY_TARGET_REPO: ' of the current repository'
221
+ GH_AW_WIKI_NOTE: ''
222
+ with:
223
+ script: |
224
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
225
+ setupGlobals(core, github, context, exec, io);
226
+
227
+ const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs');
228
+
229
+ // Call the substitution function
230
+ return await substitutePlaceholders({
231
+ file: process.env.GH_AW_PROMPT,
232
+ substitutions: {
233
+ GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
234
+ GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
235
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
236
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
237
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
238
+ GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
239
+ GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
240
+ GH_AW_GITHUB_SERVER_URL: process.env.GH_AW_GITHUB_SERVER_URL,
241
+ GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
242
+ GH_AW_MEMORY_BRANCH_NAME: process.env.GH_AW_MEMORY_BRANCH_NAME,
243
+ GH_AW_MEMORY_CONSTRAINTS: process.env.GH_AW_MEMORY_CONSTRAINTS,
244
+ GH_AW_MEMORY_DESCRIPTION: process.env.GH_AW_MEMORY_DESCRIPTION,
245
+ GH_AW_MEMORY_DIR: process.env.GH_AW_MEMORY_DIR,
246
+ GH_AW_MEMORY_TARGET_REPO: process.env.GH_AW_MEMORY_TARGET_REPO,
247
+ GH_AW_WIKI_NOTE: process.env.GH_AW_WIKI_NOTE
248
+ }
249
+ });
250
+ - name: Validate prompt placeholders
251
+ env:
252
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
253
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh
254
+ - name: Print prompt
255
+ env:
256
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
257
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh
258
+ - name: Upload activation artifact
259
+ if: success()
260
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
261
+ with:
262
+ name: activation
263
+ path: |
264
+ /tmp/gh-aw/aw_info.json
265
+ /tmp/gh-aw/aw-prompts/prompt.txt
266
+ retention-days: 1
267
+
268
+ agent:
269
+ needs: activation
270
+ runs-on: ubuntu-latest
271
+ permissions: read-all
272
+ concurrency:
273
+ group: "gh-aw-copilot-${{ github.workflow }}"
274
+ env:
275
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
276
+ GH_AW_ASSETS_ALLOWED_EXTS: ""
277
+ GH_AW_ASSETS_BRANCH: ""
278
+ GH_AW_ASSETS_MAX_SIZE_KB: 0
279
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
280
+ GH_AW_WORKFLOW_ID_SANITIZED: leansquad
281
+ outputs:
282
+ checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
283
+ detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
284
+ detection_success: ${{ steps.detection_conclusion.outputs.success }}
285
+ has_patch: ${{ steps.collect_output.outputs.has_patch }}
286
+ inference_access_error: ${{ steps.detect-inference-error.outputs.inference_access_error || 'false' }}
287
+ model: ${{ needs.activation.outputs.model }}
288
+ output: ${{ steps.collect_output.outputs.output }}
289
+ output_types: ${{ steps.collect_output.outputs.output_types }}
290
+ steps:
291
+ - name: Setup Scripts
292
+ uses: github/gh-aw-actions/setup@dc50be57c94373431b49d3d0927f318ac2bb5c4c # v0.62.5
293
+ with:
294
+ destination: ${{ runner.temp }}/gh-aw/actions
295
+ - name: Set runtime paths
296
+ run: |
297
+ echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" >> "$GITHUB_ENV"
298
+ echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" >> "$GITHUB_ENV"
299
+ echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" >> "$GITHUB_ENV"
300
+ - name: Checkout repository
301
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
302
+ with:
303
+ persist-credentials: false
304
+ - name: Setup Python
305
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
306
+ with:
307
+ python-version: '3.12'
308
+ - name: Create gh-aw temp directory
309
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh
310
+ - name: Configure gh CLI for GitHub Enterprise
311
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh
312
+ env:
313
+ GH_TOKEN: ${{ github.token }}
314
+ - env:
315
+ GH_TOKEN: ${{ github.token }}
316
+ name: Assess FV state and compute task weights
317
+ run: "mkdir -p /tmp/gh-aw\n\n# Count Lean files, excluding the .lake build cache\nfind . -name \"*.lean\" 2>/dev/null | grep -cv \"\\.lake/\" > /tmp/gh-aw/lean_count.txt || echo 0 > /tmp/gh-aw/lean_count.txt\n\n# Detect formal-verification directory\n[ -d \"formal-verification\" ] && echo 1 > /tmp/gh-aw/fv_dir.txt || echo 0 > /tmp/gh-aw/fv_dir.txt\n\n# Count markdown docs inside formal-verification/\nfind . \\( -path \"*/formal-verification/*.md\" -o -path \"*/formal-verification/specs/*.md\" \\) 2>/dev/null \\\n | wc -l > /tmp/gh-aw/fv_docs.txt || echo 0 > /tmp/gh-aw/fv_docs.txt\n\n# Fetch open FV Squad issues\ngh issue list --state open --label lean-squad --json number 2>/dev/null \\\n > /tmp/gh-aw/fv_issues.json || echo \"[]\" > /tmp/gh-aw/fv_issues.json\n\n# Fetch open FV Squad PRs\ngh pr list --state open --limit 50 --json number,title 2>/dev/null \\\n | python3 -c \"\nimport json, sys\nd = json.load(sys.stdin)\nprint(json.dumps([x for x in d if x['title'].startswith('[Lean Squad]')]))\" \\\n > /tmp/gh-aw/fv_prs.json || echo \"[]\" > /tmp/gh-aw/fv_prs.json\n\npython3 - << 'EOF'\nimport json, os, random\n\nlean_count = int(open('/tmp/gh-aw/lean_count.txt').read().strip() or 0)\nfv_dir = int(open('/tmp/gh-aw/fv_dir.txt').read().strip() or 0)\nfv_docs = int(open('/tmp/gh-aw/fv_docs.txt').read().strip() or 0)\nfv_issues = json.load(open('/tmp/gh-aw/fv_issues.json'))\nfv_prs = json.load(open('/tmp/gh-aw/fv_prs.json'))\n\nn_issues = len(fv_issues)\nn_prs = len(fv_prs)\n\ntask_names = {\n 1: 'Research & Target Identification',\n 2: 'Informal Spec Extraction',\n 3: 'Formal Spec Writing (Lean 4)',\n 4: 'Implementation Extraction',\n 5: 'Proof Assistance',\n 6: 'Maintain Open Lean Squad PRs',\n}\n\n# Phase progress heuristics derived from repo state\n# The agent refines these using repo-memory at runtime\nhas_research = bool(fv_dir) and (fv_docs >= 1 or n_issues >= 1 or lean_count >= 1)\nhas_inf_specs = fv_docs >= 2 or lean_count >= 1\nhas_lean_specs = lean_count >= 1\nhas_impl = lean_count >= 3\nhas_proofs = lean_count >= 6\n\nweights = {\n 1: 10.0 if not has_research else 2.0,\n 2: (8.0 if not has_inf_specs else 2.0) if has_research else 0.5,\n 3: (8.0 if not has_lean_specs else 2.0) if has_inf_specs else 0.3,\n 4: (6.0 if not has_impl else 2.0) if has_lean_specs else 0.2,\n 5: (6.0 if not has_proofs else 2.0) if has_impl else 0.1,\n 6: float(n_prs) * 2.0,\n}\n\nrun_id = int(os.environ.get('GITHUB_RUN_ID', '0'))\nrng = random.Random(run_id)\n\nnon_main = [t for t in weights if t != 6]\nnm_weights = [weights[t] for t in non_main]\n\nchosen, seen = [], set()\nfor t in rng.choices(non_main, weights=nm_weights, k=30):\n if t not in seen:\n seen.add(t)\n chosen.append(t)\n if len(chosen) == 2:\n break\n\nprint('=== Lean Squad Task Selection ===')\nprint(f'Lean files : {lean_count}')\nprint(f'FV dir : {bool(fv_dir)}')\nprint(f'FV docs : {fv_docs}')\nprint(f'Open issues : {n_issues}')\nprint(f'Open FV PRs : {n_prs}')\nprint(f'Phase flags : research={has_research}, inf_specs={has_inf_specs}, '\n f'lean_specs={has_lean_specs}, impl={has_impl}, proofs={has_proofs}')\nprint()\nprint('Task weights:')\nfor t, w in weights.items():\n tag = ' <-- SELECTED' if t in chosen else (' <-- if PRs open' if t == 6 else '')\n print(f' Task {t} ({task_names[t]}): weight {w:.1f}{tag}')\nprint()\nprint(f'Selected tasks: {chosen} = {[task_names[t] for t in chosen]}')\n\nresult = {\n 'lean_count': lean_count, 'fv_dir': bool(fv_dir), 'fv_docs': fv_docs,\n 'n_issues': n_issues, 'n_prs': n_prs,\n 'phase_flags': {\n 'has_research': has_research,\n 'has_inf_specs': has_inf_specs,\n 'has_lean_specs': has_lean_specs,\n 'has_impl': has_impl,\n 'has_proofs': has_proofs,\n },\n 'task_names': task_names,\n 'weights': {str(k): round(v, 2) for k, v in weights.items()},\n 'selected_tasks': chosen,\n}\nwith open('/tmp/gh-aw/task_selection.json', 'w') as f:\n json.dump(result, f, indent=2)\nEOF\n"
318
+
319
+ # Repo memory git-based storage configuration from frontmatter processed below
320
+ - name: Clone repo-memory branch (default)
321
+ env:
322
+ GH_TOKEN: ${{ github.token }}
323
+ GITHUB_SERVER_URL: ${{ github.server_url }}
324
+ BRANCH_NAME: memory/lean-squad
325
+ TARGET_REPO: ${{ github.repository }}
326
+ MEMORY_DIR: /tmp/gh-aw/repo-memory/default
327
+ CREATE_ORPHAN: true
328
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/clone_repo_memory_branch.sh
329
+ - name: Configure Git credentials
330
+ env:
331
+ REPO_NAME: ${{ github.repository }}
332
+ SERVER_URL: ${{ github.server_url }}
333
+ run: |
334
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
335
+ git config --global user.name "github-actions[bot]"
336
+ git config --global am.keepcr true
337
+ # Re-authenticate git with GitHub token
338
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
339
+ git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
340
+ echo "Git configured with standard GitHub Actions identity"
341
+ - name: Checkout PR branch
342
+ id: checkout-pr
343
+ if: |
344
+ github.event.pull_request || github.event.issue.pull_request
345
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
346
+ env:
347
+ GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
348
+ with:
349
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
350
+ script: |
351
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
352
+ setupGlobals(core, github, context, exec, io);
353
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
354
+ await main();
355
+ - name: Install GitHub Copilot CLI
356
+ run: ${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh latest
357
+ env:
358
+ GH_HOST: github.com
359
+ - name: Install AWF binary
360
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh v0.24.5
361
+ - name: Determine automatic lockdown mode for GitHub MCP Server
362
+ id: determine-automatic-lockdown
363
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
364
+ env:
365
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
366
+ GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
367
+ with:
368
+ script: |
369
+ const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs');
370
+ await determineAutomaticLockdown(github, context, core);
371
+ - name: Download container images
372
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.24.5 ghcr.io/github/gh-aw-firewall/api-proxy:0.24.5 ghcr.io/github/gh-aw-firewall/squid:0.24.5 ghcr.io/github/gh-aw-mcpg:v0.1.20 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine
373
+ - name: Write Safe Outputs Config
374
+ run: |
375
+ mkdir -p ${RUNNER_TEMP}/gh-aw/safeoutputs
376
+ mkdir -p /tmp/gh-aw/safeoutputs
377
+ mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
378
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF'
379
+ {"add_comment":{"max":3,"target":"*"},"create_issue":{"max":4},"create_pull_request":{"draft":true,"max":2,"title_prefix":"[Lean Squad] "},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":10240,"max_patch_size":102400}]},"update_issue":{"max":1}}
380
+ GH_AW_SAFE_OUTPUTS_CONFIG_EOF
381
+ - name: Write Safe Outputs Tools
382
+ run: |
383
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF'
384
+ {
385
+ "description_suffixes": {
386
+ "add_comment": " CONSTRAINTS: Maximum 3 comment(s) can be added. Target: *.",
387
+ "create_issue": " CONSTRAINTS: Maximum 4 issue(s) can be created. Title will be prefixed with \"[Lean Squad] \". Labels [\"automation\" \"lean-squad\"] will be automatically added.",
388
+ "create_pull_request": " CONSTRAINTS: Maximum 2 pull request(s) can be created. Title will be prefixed with \"[Lean Squad] \". Labels [\"automation\" \"lean-squad\"] will be automatically added. PRs will be created as drafts.",
389
+ "update_issue": " CONSTRAINTS: Maximum 1 issue(s) can be updated. Target: *. The target issue title must start with \"[Lean Squad] \"."
390
+ },
391
+ "repo_params": {},
392
+ "dynamic_tools": []
393
+ }
394
+ GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF
395
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF'
396
+ {
397
+ "add_comment": {
398
+ "defaultMax": 1,
399
+ "fields": {
400
+ "body": {
401
+ "required": true,
402
+ "type": "string",
403
+ "sanitize": true,
404
+ "maxLength": 65000
405
+ },
406
+ "item_number": {
407
+ "issueOrPRNumber": true
408
+ },
409
+ "repo": {
410
+ "type": "string",
411
+ "maxLength": 256
412
+ }
413
+ }
414
+ },
415
+ "create_issue": {
416
+ "defaultMax": 1,
417
+ "fields": {
418
+ "body": {
419
+ "required": true,
420
+ "type": "string",
421
+ "sanitize": true,
422
+ "maxLength": 65000
423
+ },
424
+ "labels": {
425
+ "type": "array",
426
+ "itemType": "string",
427
+ "itemSanitize": true,
428
+ "itemMaxLength": 128
429
+ },
430
+ "parent": {
431
+ "issueOrPRNumber": true
432
+ },
433
+ "repo": {
434
+ "type": "string",
435
+ "maxLength": 256
436
+ },
437
+ "temporary_id": {
438
+ "type": "string"
439
+ },
440
+ "title": {
441
+ "required": true,
442
+ "type": "string",
443
+ "sanitize": true,
444
+ "maxLength": 128
445
+ }
446
+ }
447
+ },
448
+ "create_pull_request": {
449
+ "defaultMax": 1,
450
+ "fields": {
451
+ "body": {
452
+ "required": true,
453
+ "type": "string",
454
+ "sanitize": true,
455
+ "maxLength": 65000
456
+ },
457
+ "branch": {
458
+ "required": true,
459
+ "type": "string",
460
+ "sanitize": true,
461
+ "maxLength": 256
462
+ },
463
+ "draft": {
464
+ "type": "boolean"
465
+ },
466
+ "labels": {
467
+ "type": "array",
468
+ "itemType": "string",
469
+ "itemSanitize": true,
470
+ "itemMaxLength": 128
471
+ },
472
+ "repo": {
473
+ "type": "string",
474
+ "maxLength": 256
475
+ },
476
+ "title": {
477
+ "required": true,
478
+ "type": "string",
479
+ "sanitize": true,
480
+ "maxLength": 128
481
+ }
482
+ }
483
+ },
484
+ "missing_data": {
485
+ "defaultMax": 20,
486
+ "fields": {
487
+ "alternatives": {
488
+ "type": "string",
489
+ "sanitize": true,
490
+ "maxLength": 256
491
+ },
492
+ "context": {
493
+ "type": "string",
494
+ "sanitize": true,
495
+ "maxLength": 256
496
+ },
497
+ "data_type": {
498
+ "type": "string",
499
+ "sanitize": true,
500
+ "maxLength": 128
501
+ },
502
+ "reason": {
503
+ "type": "string",
504
+ "sanitize": true,
505
+ "maxLength": 256
506
+ }
507
+ }
508
+ },
509
+ "missing_tool": {
510
+ "defaultMax": 20,
511
+ "fields": {
512
+ "alternatives": {
513
+ "type": "string",
514
+ "sanitize": true,
515
+ "maxLength": 512
516
+ },
517
+ "reason": {
518
+ "required": true,
519
+ "type": "string",
520
+ "sanitize": true,
521
+ "maxLength": 256
522
+ },
523
+ "tool": {
524
+ "type": "string",
525
+ "sanitize": true,
526
+ "maxLength": 128
527
+ }
528
+ }
529
+ },
530
+ "noop": {
531
+ "defaultMax": 1,
532
+ "fields": {
533
+ "message": {
534
+ "required": true,
535
+ "type": "string",
536
+ "sanitize": true,
537
+ "maxLength": 65000
538
+ }
539
+ }
540
+ },
541
+ "update_issue": {
542
+ "defaultMax": 1,
543
+ "fields": {
544
+ "assignees": {
545
+ "type": "array",
546
+ "itemType": "string",
547
+ "itemSanitize": true,
548
+ "itemMaxLength": 39
549
+ },
550
+ "body": {
551
+ "type": "string",
552
+ "sanitize": true,
553
+ "maxLength": 65000
554
+ },
555
+ "issue_number": {
556
+ "issueOrPRNumber": true
557
+ },
558
+ "labels": {
559
+ "type": "array",
560
+ "itemType": "string",
561
+ "itemSanitize": true,
562
+ "itemMaxLength": 128
563
+ },
564
+ "milestone": {
565
+ "optionalPositiveInteger": true
566
+ },
567
+ "operation": {
568
+ "type": "string",
569
+ "enum": [
570
+ "replace",
571
+ "append",
572
+ "prepend",
573
+ "replace-island"
574
+ ]
575
+ },
576
+ "repo": {
577
+ "type": "string",
578
+ "maxLength": 256
579
+ },
580
+ "status": {
581
+ "type": "string",
582
+ "enum": [
583
+ "open",
584
+ "closed"
585
+ ]
586
+ },
587
+ "title": {
588
+ "type": "string",
589
+ "sanitize": true,
590
+ "maxLength": 128
591
+ }
592
+ },
593
+ "customValidation": "requiresOneOf:status,title,body"
594
+ }
595
+ }
596
+ GH_AW_SAFE_OUTPUTS_VALIDATION_EOF
597
+ node ${RUNNER_TEMP}/gh-aw/actions/generate_safe_outputs_tools.cjs
598
+ - name: Generate Safe Outputs MCP Server Config
599
+ id: safe-outputs-config
600
+ run: |
601
+ # Generate a secure random API key (360 bits of entropy, 40+ chars)
602
+ # Mask immediately to prevent timing vulnerabilities
603
+ API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
604
+ echo "::add-mask::${API_KEY}"
605
+
606
+ PORT=3001
607
+
608
+ # Set outputs for next steps
609
+ {
610
+ echo "safe_outputs_api_key=${API_KEY}"
611
+ echo "safe_outputs_port=${PORT}"
612
+ } >> "$GITHUB_OUTPUT"
613
+
614
+ echo "Safe Outputs MCP server will run on port ${PORT}"
615
+
616
+ - name: Start Safe Outputs MCP HTTP Server
617
+ id: safe-outputs-start
618
+ env:
619
+ DEBUG: '*'
620
+ GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }}
621
+ GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }}
622
+ GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json
623
+ GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json
624
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
625
+ run: |
626
+ # Environment variables are set above to prevent template injection
627
+ export DEBUG
628
+ export GH_AW_SAFE_OUTPUTS_PORT
629
+ export GH_AW_SAFE_OUTPUTS_API_KEY
630
+ export GH_AW_SAFE_OUTPUTS_TOOLS_PATH
631
+ export GH_AW_SAFE_OUTPUTS_CONFIG_PATH
632
+ export GH_AW_MCP_LOG_DIR
633
+
634
+ bash ${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh
635
+
636
+ - name: Start MCP Gateway
637
+ id: start-mcp-gateway
638
+ env:
639
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
640
+ GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }}
641
+ GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }}
642
+ GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }}
643
+ GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }}
644
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
645
+ run: |
646
+ set -eo pipefail
647
+ mkdir -p /tmp/gh-aw/mcp-config
648
+
649
+ # Export gateway environment variables for MCP config and gateway script
650
+ export MCP_GATEWAY_PORT="80"
651
+ export MCP_GATEWAY_DOMAIN="host.docker.internal"
652
+ MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
653
+ echo "::add-mask::${MCP_GATEWAY_API_KEY}"
654
+ export MCP_GATEWAY_API_KEY
655
+ export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
656
+ mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
657
+ export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
658
+ export DEBUG="*"
659
+
660
+ export GH_AW_ENGINE="copilot"
661
+ export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.20'
662
+
663
+ mkdir -p /home/runner/.copilot
664
+ cat << GH_AW_MCP_CONFIG_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh
665
+ {
666
+ "mcpServers": {
667
+ "github": {
668
+ "type": "stdio",
669
+ "container": "ghcr.io/github/github-mcp-server:v0.32.0",
670
+ "env": {
671
+ "GITHUB_HOST": "\${GITHUB_SERVER_URL}",
672
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
673
+ "GITHUB_READ_ONLY": "1",
674
+ "GITHUB_TOOLSETS": "context,repos,issues,pull_requests"
675
+ },
676
+ "guard-policies": {
677
+ "allow-only": {
678
+ "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY",
679
+ "repos": "$GITHUB_MCP_GUARD_REPOS"
680
+ }
681
+ }
682
+ },
683
+ "safeoutputs": {
684
+ "type": "http",
685
+ "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
686
+ "headers": {
687
+ "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}"
688
+ },
689
+ "guard-policies": {
690
+ "write-sink": {
691
+ "accept": [
692
+ "*"
693
+ ]
694
+ }
695
+ }
696
+ }
697
+ },
698
+ "gateway": {
699
+ "port": $MCP_GATEWAY_PORT,
700
+ "domain": "${MCP_GATEWAY_DOMAIN}",
701
+ "apiKey": "${MCP_GATEWAY_API_KEY}",
702
+ "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
703
+ }
704
+ }
705
+ GH_AW_MCP_CONFIG_EOF
706
+ - name: Download activation artifact
707
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
708
+ with:
709
+ name: activation
710
+ path: /tmp/gh-aw
711
+ - name: Clean git credentials
712
+ continue-on-error: true
713
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh
714
+ - name: Execute GitHub Copilot CLI
715
+ id: agentic_execution
716
+ # Copilot CLI tool arguments (sorted):
717
+ timeout-minutes: 20
718
+ run: |
719
+ set -o pipefail
720
+ touch /tmp/gh-aw/agent-step-summary.md
721
+ # shellcheck disable=SC1003
722
+ sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,arxiv.org,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,leanprover-community.github.io,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.5 --skip-pull --enable-api-proxy \
723
+ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
724
+ env:
725
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
726
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
727
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
728
+ GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
729
+ GH_AW_PHASE: agent
730
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
731
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
732
+ GH_AW_VERSION: v0.62.5
733
+ GITHUB_API_URL: ${{ github.api_url }}
734
+ GITHUB_AW: true
735
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
736
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
737
+ GITHUB_REF_NAME: ${{ github.ref_name }}
738
+ GITHUB_SERVER_URL: ${{ github.server_url }}
739
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
740
+ GITHUB_WORKSPACE: ${{ github.workspace }}
741
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
742
+ GIT_AUTHOR_NAME: github-actions[bot]
743
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
744
+ GIT_COMMITTER_NAME: github-actions[bot]
745
+ XDG_CONFIG_HOME: /home/runner
746
+ - name: Detect inference access error
747
+ id: detect-inference-error
748
+ if: always()
749
+ continue-on-error: true
750
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/detect_inference_access_error.sh
751
+ - name: Configure Git credentials
752
+ env:
753
+ REPO_NAME: ${{ github.repository }}
754
+ SERVER_URL: ${{ github.server_url }}
755
+ run: |
756
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
757
+ git config --global user.name "github-actions[bot]"
758
+ git config --global am.keepcr true
759
+ # Re-authenticate git with GitHub token
760
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
761
+ git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
762
+ echo "Git configured with standard GitHub Actions identity"
763
+ - name: Copy Copilot session state files to logs
764
+ if: always()
765
+ continue-on-error: true
766
+ run: |
767
+ # Copy Copilot session state files to logs folder for artifact collection
768
+ # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them
769
+ SESSION_STATE_DIR="$HOME/.copilot/session-state"
770
+ LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs"
771
+
772
+ if [ -d "$SESSION_STATE_DIR" ]; then
773
+ echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR"
774
+ mkdir -p "$LOGS_DIR"
775
+ cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true
776
+ echo "Session state files copied successfully"
777
+ else
778
+ echo "No session-state directory found at $SESSION_STATE_DIR"
779
+ fi
780
+ - name: Stop MCP Gateway
781
+ if: always()
782
+ continue-on-error: true
783
+ env:
784
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
785
+ MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
786
+ GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
787
+ run: |
788
+ bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
789
+ - name: Redact secrets in logs
790
+ if: always()
791
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
792
+ with:
793
+ script: |
794
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
795
+ setupGlobals(core, github, context, exec, io);
796
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
797
+ await main();
798
+ env:
799
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
800
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
801
+ SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
802
+ SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
803
+ SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
804
+ - name: Append agent step summary
805
+ if: always()
806
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh
807
+ - name: Copy Safe Outputs
808
+ if: always()
809
+ run: |
810
+ mkdir -p /tmp/gh-aw
811
+ cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
812
+ - name: Ingest agent output
813
+ id: collect_output
814
+ if: always()
815
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
816
+ env:
817
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
818
+ GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,arxiv.org,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,leanprover-community.github.io,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
819
+ GITHUB_SERVER_URL: ${{ github.server_url }}
820
+ GITHUB_API_URL: ${{ github.api_url }}
821
+ with:
822
+ script: |
823
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
824
+ setupGlobals(core, github, context, exec, io);
825
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs');
826
+ await main();
827
+ - name: Parse agent logs for step summary
828
+ if: always()
829
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
830
+ env:
831
+ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
832
+ with:
833
+ script: |
834
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
835
+ setupGlobals(core, github, context, exec, io);
836
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs');
837
+ await main();
838
+ - name: Parse MCP Gateway logs for step summary
839
+ if: always()
840
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
841
+ with:
842
+ script: |
843
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
844
+ setupGlobals(core, github, context, exec, io);
845
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs');
846
+ await main();
847
+ - name: Print firewall logs
848
+ if: always()
849
+ continue-on-error: true
850
+ env:
851
+ AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
852
+ run: |
853
+ # Fix permissions on firewall logs so they can be uploaded as artifacts
854
+ # AWF runs with sudo, creating files owned by root
855
+ sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true
856
+ # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
857
+ if command -v awf &> /dev/null; then
858
+ awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
859
+ else
860
+ echo 'AWF binary not installed, skipping firewall log summary'
861
+ fi
862
+ # Upload repo memory as artifacts for push job
863
+ - name: Upload repo-memory artifact (default)
864
+ if: always()
865
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
866
+ with:
867
+ name: repo-memory-default
868
+ path: /tmp/gh-aw/repo-memory/default
869
+ retention-days: 1
870
+ if-no-files-found: ignore
871
+ - name: Upload agent artifacts
872
+ if: always()
873
+ continue-on-error: true
874
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
875
+ with:
876
+ name: agent
877
+ path: |
878
+ /tmp/gh-aw/aw-prompts/prompt.txt
879
+ /tmp/gh-aw/sandbox/agent/logs/
880
+ /tmp/gh-aw/redacted-urls.log
881
+ /tmp/gh-aw/mcp-logs/
882
+ /tmp/gh-aw/sandbox/firewall/logs/
883
+ /tmp/gh-aw/agent-stdio.log
884
+ /tmp/gh-aw/agent/
885
+ /tmp/gh-aw/safeoutputs.jsonl
886
+ /tmp/gh-aw/agent_output.json
887
+ /tmp/gh-aw/aw-*.patch
888
+ if-no-files-found: ignore
889
+ # --- Threat Detection (inline) ---
890
+ - name: Check if detection needed
891
+ id: detection_guard
892
+ if: always()
893
+ env:
894
+ OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }}
895
+ HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
896
+ run: |
897
+ if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
898
+ echo "run_detection=true" >> "$GITHUB_OUTPUT"
899
+ echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
900
+ else
901
+ echo "run_detection=false" >> "$GITHUB_OUTPUT"
902
+ echo "Detection skipped: no agent outputs or patches to analyze"
903
+ fi
904
+ - name: Clear MCP configuration for detection
905
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
906
+ run: |
907
+ rm -f /tmp/gh-aw/mcp-config/mcp-servers.json
908
+ rm -f /home/runner/.copilot/mcp-config.json
909
+ rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
910
+ - name: Prepare threat detection files
911
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
912
+ run: |
913
+ mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
914
+ cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
915
+ cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
916
+ for f in /tmp/gh-aw/aw-*.patch; do
917
+ [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
918
+ done
919
+ echo "Prepared threat detection files:"
920
+ ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
921
+ - name: Setup threat detection
922
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
923
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
924
+ env:
925
+ WORKFLOW_NAME: "Lean Squad"
926
+ WORKFLOW_DESCRIPTION: "Lean Squad: an optimistic multi-phase system that progressively applies\nLean 4 formal verification to your codebase, one target at a time.\n\nEach run selects tasks weighted to current FV progress:\n1. Research — survey codebase, identify FV-amenable targets, document approach\n2. Informal Spec Extraction — extract design intentions and informal contracts\n3. Formal Spec Writing — write Lean 4 type signatures and property statements\n4. Implementation Extraction — translate code to a Lean-verifiable functional model\n5. Proof Assistance — attempt proofs, find counterexamples, report bugs\n6. Maintain Open Lean Squad PRs — fix CI failures and merge conflicts in open Lean Squad PRs\n\nPhases are sequentially weighted: Task 1 dominates until research is done,\nthen Task 2 rises, and so on up to proofs. Each run builds on prior runs\n(assumes merged PRs). Notes, targets, choices, and progress live in repo-memory.\nOutputs are pull requests (specs, proofs) and issues (bugs, status)."
927
+ HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
928
+ with:
929
+ script: |
930
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
931
+ setupGlobals(core, github, context, exec, io);
932
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs');
933
+ await main();
934
+ - name: Ensure threat-detection directory and log
935
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
936
+ run: |
937
+ mkdir -p /tmp/gh-aw/threat-detection
938
+ touch /tmp/gh-aw/threat-detection/detection.log
939
+ - name: Execute GitHub Copilot CLI
940
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
941
+ id: detection_agentic_execution
942
+ # Copilot CLI tool arguments (sorted):
943
+ # --allow-tool shell(cat)
944
+ # --allow-tool shell(grep)
945
+ # --allow-tool shell(head)
946
+ # --allow-tool shell(jq)
947
+ # --allow-tool shell(ls)
948
+ # --allow-tool shell(tail)
949
+ # --allow-tool shell(wc)
950
+ timeout-minutes: 20
951
+ run: |
952
+ set -o pipefail
953
+ touch /tmp/gh-aw/agent-step-summary.md
954
+ # shellcheck disable=SC1003
955
+ sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.5 --skip-pull --enable-api-proxy \
956
+ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
957
+ env:
958
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
959
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
960
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }}
961
+ GH_AW_PHASE: detection
962
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
963
+ GH_AW_VERSION: v0.62.5
964
+ GITHUB_API_URL: ${{ github.api_url }}
965
+ GITHUB_AW: true
966
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
967
+ GITHUB_REF_NAME: ${{ github.ref_name }}
968
+ GITHUB_SERVER_URL: ${{ github.server_url }}
969
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
970
+ GITHUB_WORKSPACE: ${{ github.workspace }}
971
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
972
+ GIT_AUTHOR_NAME: github-actions[bot]
973
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
974
+ GIT_COMMITTER_NAME: github-actions[bot]
975
+ XDG_CONFIG_HOME: /home/runner
976
+ - name: Parse threat detection results
977
+ id: parse_detection_results
978
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
979
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
980
+ with:
981
+ script: |
982
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
983
+ setupGlobals(core, github, context, exec, io);
984
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs');
985
+ await main();
986
+ - name: Upload threat detection log
987
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
988
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
989
+ with:
990
+ name: detection
991
+ path: /tmp/gh-aw/threat-detection/detection.log
992
+ if-no-files-found: ignore
993
+ - name: Set detection conclusion
994
+ id: detection_conclusion
995
+ if: always()
996
+ env:
997
+ RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
998
+ DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }}
999
+ run: |
1000
+ if [[ "$RUN_DETECTION" != "true" ]]; then
1001
+ echo "conclusion=skipped" >> "$GITHUB_OUTPUT"
1002
+ echo "success=true" >> "$GITHUB_OUTPUT"
1003
+ echo "Detection was not needed, marking as skipped"
1004
+ elif [[ "$DETECTION_SUCCESS" == "true" ]]; then
1005
+ echo "conclusion=success" >> "$GITHUB_OUTPUT"
1006
+ echo "success=true" >> "$GITHUB_OUTPUT"
1007
+ echo "Detection passed successfully"
1008
+ else
1009
+ echo "conclusion=failure" >> "$GITHUB_OUTPUT"
1010
+ echo "success=false" >> "$GITHUB_OUTPUT"
1011
+ echo "Detection found issues"
1012
+ fi
1013
+
1014
+ conclusion:
1015
+ needs:
1016
+ - activation
1017
+ - agent
1018
+ - push_repo_memory
1019
+ - safe_outputs
1020
+ if: always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true')
1021
+ runs-on: ubuntu-slim
1022
+ permissions:
1023
+ contents: write
1024
+ discussions: write
1025
+ issues: write
1026
+ pull-requests: write
1027
+ concurrency:
1028
+ group: "gh-aw-conclusion-lean-squad"
1029
+ cancel-in-progress: false
1030
+ outputs:
1031
+ noop_message: ${{ steps.noop.outputs.noop_message }}
1032
+ tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
1033
+ total_count: ${{ steps.missing_tool.outputs.total_count }}
1034
+ steps:
1035
+ - name: Setup Scripts
1036
+ uses: github/gh-aw-actions/setup@dc50be57c94373431b49d3d0927f318ac2bb5c4c # v0.62.5
1037
+ with:
1038
+ destination: ${{ runner.temp }}/gh-aw/actions
1039
+ - name: Download agent output artifact
1040
+ id: download-agent-output
1041
+ continue-on-error: true
1042
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1043
+ with:
1044
+ name: agent
1045
+ path: /tmp/gh-aw/
1046
+ - name: Setup agent output environment variable
1047
+ if: steps.download-agent-output.outcome == 'success'
1048
+ run: |
1049
+ mkdir -p /tmp/gh-aw/
1050
+ find "/tmp/gh-aw/" -type f -print
1051
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV"
1052
+ - name: Process No-Op Messages
1053
+ id: noop
1054
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1055
+ env:
1056
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1057
+ GH_AW_NOOP_MAX: "1"
1058
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1059
+ with:
1060
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1061
+ script: |
1062
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1063
+ setupGlobals(core, github, context, exec, io);
1064
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/noop.cjs');
1065
+ await main();
1066
+ - name: Record Missing Tool
1067
+ id: missing_tool
1068
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1069
+ env:
1070
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1071
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1072
+ with:
1073
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1074
+ script: |
1075
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1076
+ setupGlobals(core, github, context, exec, io);
1077
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs');
1078
+ await main();
1079
+ - name: Handle Agent Failure
1080
+ id: handle_agent_failure
1081
+ if: always()
1082
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1083
+ env:
1084
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1085
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1086
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1087
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1088
+ GH_AW_WORKFLOW_ID: "lean-squad"
1089
+ GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
1090
+ GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
1091
+ GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
1092
+ GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }}
1093
+ GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }}
1094
+ GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
1095
+ GH_AW_PUSH_REPO_MEMORY_RESULT: ${{ needs.push_repo_memory.result }}
1096
+ GH_AW_REPO_MEMORY_VALIDATION_FAILED_default: ${{ needs.push_repo_memory.outputs.validation_failed_default }}
1097
+ GH_AW_REPO_MEMORY_VALIDATION_ERROR_default: ${{ needs.push_repo_memory.outputs.validation_error_default }}
1098
+ GH_AW_REPO_MEMORY_PATCH_SIZE_EXCEEDED_default: ${{ needs.push_repo_memory.outputs.patch_size_exceeded_default }}
1099
+ GH_AW_GROUP_REPORTS: "false"
1100
+ GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
1101
+ GH_AW_TIMEOUT_MINUTES: "20"
1102
+ with:
1103
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1104
+ script: |
1105
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1106
+ setupGlobals(core, github, context, exec, io);
1107
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs');
1108
+ await main();
1109
+ - name: Handle No-Op Message
1110
+ id: handle_noop_message
1111
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1112
+ env:
1113
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1114
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1115
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1116
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1117
+ GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }}
1118
+ GH_AW_NOOP_REPORT_AS_ISSUE: "true"
1119
+ with:
1120
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1121
+ script: |
1122
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1123
+ setupGlobals(core, github, context, exec, io);
1124
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs');
1125
+ await main();
1126
+ - name: Handle Create Pull Request Error
1127
+ id: handle_create_pr_error
1128
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1129
+ env:
1130
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1131
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1132
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1133
+ with:
1134
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1135
+ script: |
1136
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1137
+ setupGlobals(core, github, context, exec, io);
1138
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_create_pr_error.cjs');
1139
+ await main();
1140
+
1141
+ push_repo_memory:
1142
+ needs: agent
1143
+ if: always() && needs.agent.outputs.detection_success == 'true'
1144
+ runs-on: ubuntu-latest
1145
+ permissions:
1146
+ contents: write
1147
+ concurrency:
1148
+ group: "push-repo-memory-${{ github.repository }}"
1149
+ cancel-in-progress: false
1150
+ outputs:
1151
+ patch_size_exceeded_default: ${{ steps.push_repo_memory_default.outputs.patch_size_exceeded }}
1152
+ validation_error_default: ${{ steps.push_repo_memory_default.outputs.validation_error }}
1153
+ validation_failed_default: ${{ steps.push_repo_memory_default.outputs.validation_failed }}
1154
+ steps:
1155
+ - name: Setup Scripts
1156
+ uses: github/gh-aw-actions/setup@dc50be57c94373431b49d3d0927f318ac2bb5c4c # v0.62.5
1157
+ with:
1158
+ destination: ${{ runner.temp }}/gh-aw/actions
1159
+ - name: Checkout repository
1160
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1161
+ with:
1162
+ persist-credentials: false
1163
+ sparse-checkout: .
1164
+ - name: Configure Git credentials
1165
+ env:
1166
+ REPO_NAME: ${{ github.repository }}
1167
+ SERVER_URL: ${{ github.server_url }}
1168
+ run: |
1169
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
1170
+ git config --global user.name "github-actions[bot]"
1171
+ git config --global am.keepcr true
1172
+ # Re-authenticate git with GitHub token
1173
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
1174
+ git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
1175
+ echo "Git configured with standard GitHub Actions identity"
1176
+ - name: Download repo-memory artifact (default)
1177
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1178
+ continue-on-error: true
1179
+ with:
1180
+ name: repo-memory-default
1181
+ path: /tmp/gh-aw/repo-memory/default
1182
+ - name: Push repo-memory changes (default)
1183
+ id: push_repo_memory_default
1184
+ if: always()
1185
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1186
+ env:
1187
+ GH_TOKEN: ${{ github.token }}
1188
+ GITHUB_RUN_ID: ${{ github.run_id }}
1189
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1190
+ ARTIFACT_DIR: /tmp/gh-aw/repo-memory/default
1191
+ MEMORY_ID: default
1192
+ TARGET_REPO: ${{ github.repository }}
1193
+ BRANCH_NAME: memory/lean-squad
1194
+ MAX_FILE_SIZE: 10240
1195
+ MAX_FILE_COUNT: 100
1196
+ MAX_PATCH_SIZE: 102400
1197
+ ALLOWED_EXTENSIONS: '[]'
1198
+ with:
1199
+ script: |
1200
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1201
+ setupGlobals(core, github, context, exec, io);
1202
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/push_repo_memory.cjs');
1203
+ await main();
1204
+
1205
+ safe_outputs:
1206
+ needs:
1207
+ - activation
1208
+ - agent
1209
+ if: (!cancelled()) && needs.agent.result != 'skipped' && needs.agent.outputs.detection_success == 'true'
1210
+ runs-on: ubuntu-slim
1211
+ permissions:
1212
+ contents: write
1213
+ discussions: write
1214
+ issues: write
1215
+ pull-requests: write
1216
+ timeout-minutes: 15
1217
+ env:
1218
+ GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/lean-squad"
1219
+ GH_AW_ENGINE_ID: "copilot"
1220
+ GH_AW_WORKFLOW_ID: "lean-squad"
1221
+ GH_AW_WORKFLOW_NAME: "Lean Squad"
1222
+ outputs:
1223
+ code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
1224
+ code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
1225
+ comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }}
1226
+ comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }}
1227
+ create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
1228
+ create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
1229
+ created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }}
1230
+ created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }}
1231
+ created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
1232
+ created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
1233
+ process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
1234
+ process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
1235
+ steps:
1236
+ - name: Setup Scripts
1237
+ uses: github/gh-aw-actions/setup@dc50be57c94373431b49d3d0927f318ac2bb5c4c # v0.62.5
1238
+ with:
1239
+ destination: ${{ runner.temp }}/gh-aw/actions
1240
+ - name: Download agent output artifact
1241
+ id: download-agent-output
1242
+ continue-on-error: true
1243
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1244
+ with:
1245
+ name: agent
1246
+ path: /tmp/gh-aw/
1247
+ - name: Setup agent output environment variable
1248
+ if: steps.download-agent-output.outcome == 'success'
1249
+ run: |
1250
+ mkdir -p /tmp/gh-aw/
1251
+ find "/tmp/gh-aw/" -type f -print
1252
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV"
1253
+ - name: Download patch artifact
1254
+ continue-on-error: true
1255
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1256
+ with:
1257
+ name: agent
1258
+ path: /tmp/gh-aw/
1259
+ - name: Checkout repository
1260
+ if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
1261
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1262
+ with:
1263
+ ref: ${{ github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }}
1264
+ token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1265
+ persist-credentials: false
1266
+ fetch-depth: 1
1267
+ - name: Configure Git credentials
1268
+ if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
1269
+ env:
1270
+ REPO_NAME: ${{ github.repository }}
1271
+ SERVER_URL: ${{ github.server_url }}
1272
+ GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1273
+ run: |
1274
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
1275
+ git config --global user.name "github-actions[bot]"
1276
+ git config --global am.keepcr true
1277
+ # Re-authenticate git with GitHub token
1278
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
1279
+ git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
1280
+ echo "Git configured with standard GitHub Actions identity"
1281
+ - name: Configure GH_HOST for enterprise compatibility
1282
+ shell: bash
1283
+ run: |
1284
+ # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
1285
+ # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
1286
+ GH_HOST="${GITHUB_SERVER_URL#https://}"
1287
+ GH_HOST="${GH_HOST#http://}"
1288
+ echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
1289
+ - name: Process Safe Outputs
1290
+ id: process_safe_outputs
1291
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1292
+ env:
1293
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
1294
+ GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,arxiv.org,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,leanprover-community.github.io,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
1295
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1296
+ GITHUB_API_URL: ${{ github.api_url }}
1297
+ GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"create_issue\":{\"labels\":[\"automation\",\"lean-squad\"],\"max\":4,\"title_prefix\":\"[Lean Squad] \"},\"create_pull_request\":{\"draft\":true,\"labels\":[\"automation\",\"lean-squad\"],\"max\":2,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"],\"title_prefix\":\"[Lean Squad] \"},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"update_issue\":{\"allow_body\":true,\"max\":1,\"target\":\"*\",\"title_prefix\":\"[Lean Squad] \"}}"
1298
+ GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }}
1299
+ with:
1300
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1301
+ script: |
1302
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1303
+ setupGlobals(core, github, context, exec, io);
1304
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs');
1305
+ await main();
1306
+ - name: Upload safe output items
1307
+ if: always()
1308
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
1309
+ with:
1310
+ name: safe-output-items
1311
+ path: /tmp/gh-aw/safe-output-items.jsonl
1312
+ if-no-files-found: ignore
1313
+