From fe47ae13a1564aa6346ba3fff57d0c4cdd3dde40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 04:45:19 +0000 Subject: [PATCH 1/3] Initial plan From 83bbbb67f9537925c4939ecb60fedc273d9f4f44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 05:02:52 +0000 Subject: [PATCH 2/3] feat(copilot-opt): reduce initial context by moving Phases 2-5 to skill blocks and adding guards - Move Phase 2 (Performance Analysis) to skill 'opt-phase-performance' - Move Phase 3 (PR Cross-Analysis) to skill 'opt-phase-pr-analysis' - Move Phase 4 (Recommendation Selection) to skill 'opt-phase-recommendations' - Move Phase 5 (Issue Creation) to skill 'opt-phase-issue-creation' - Add token budget guard step: warns when estimated first-turn input exceeds 50k tokens - Add trim-large-session-logs step: strips boilerplate from session files >10KB before agent reads them - Recompile copilot-opt.lock.yml Closes #46903 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/copilot-opt.lock.yml | 6 +- .github/workflows/copilot-opt.md | 136 ++++++++++++++++++------- 2 files changed, 102 insertions(+), 40 deletions(-) diff --git a/.github/workflows/copilot-opt.lock.yml b/.github/workflows/copilot-opt.lock.yml index bf298891e35..05904a3119e 100644 --- a/.github/workflows/copilot-opt.lock.yml +++ b/.github/workflows/copilot-opt.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"31dd497045bc45e3682729256f80085ed8eb5eba28e438e48e67fff0f912e155","body_hash":"b21ce191d2946c1c42550a0fd67e4408b53857a8f79af3c312678cd1fc8b8962","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.71","copilot-sdk":"1.0.7"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"10c827708e77b389be48817ce9266b917f70a55dd01ce4718cefad64c963551d","body_hash":"71b67df8a9f211ce9b8791cc06df67e553f5febed6b4b356550090e62c439b60","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.71","copilot-sdk":"1.0.7"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37","digest":"sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37@sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37","digest":"sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37@sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.37","digest":"sha256:1d5300d9b08e1c4f2ad1830860656a0656383a83280058f17e805a7c3ecda203","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.37@sha256:1d5300d9b08e1c4f2ad1830860656a0656383a83280058f17e805a7c3ecda203"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37","digest":"sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37@sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.1","digest":"sha256:ad2a979c2cd8b50098e84938ca9c9c1580eb8e91526f101a90adfba7859b2c32","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.1@sha256:ad2a979c2cd8b50098e84938ca9c9c1580eb8e91526f101a90adfba7859b2c32"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.6.0","digest":"sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3","pinned_image":"ghcr.io/github/github-mcp-server:v1.6.0@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -532,6 +532,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} name: Fetch Copilot PR data run: "# Create output directories\nmkdir -p /tmp/gh-aw/agent/pr-data\nmkdir -p /tmp/gh-aw/cache-memory\n\n# Get today's date for cache identification\nTODAY=$(date '+%Y-%m-%d')\nCACHE_DIR=\"/tmp/gh-aw/cache-memory\"\n\n# Check if cached data exists from today\nif [ -f \"$CACHE_DIR/copilot-prs-${TODAY}.json\" ] && [ -s \"$CACHE_DIR/copilot-prs-${TODAY}.json\" ]; then\n echo \"✓ Found cached PR data from ${TODAY}\"\n cp \"$CACHE_DIR/copilot-prs-${TODAY}.json\" /tmp/gh-aw/agent/pr-data/copilot-prs.json\n \n # Regenerate schema if missing\n if [ ! -f \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\" ]; then\n ./.github/skills/jqschema/jqschema.sh < /tmp/gh-aw/agent/pr-data/copilot-prs.json > \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\"\n fi\n cp \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\" /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\n \n echo \"Using cached data from ${TODAY}\"\n echo \"Total PRs in cache: $(jq 'length' /tmp/gh-aw/agent/pr-data/copilot-prs.json)\"\nelse\n echo \"⬇ Downloading fresh PR data...\"\n \n # Calculate date 30 days ago\n DATE_30_DAYS_AGO=$(date -d '30 days ago' '+%Y-%m-%d' 2>/dev/null || date -v-30d '+%Y-%m-%d')\n\n # Search for PRs from copilot/* branches in the last 30 days using gh CLI\n # Using branch prefix search (head:copilot/) instead of author for reliability\n echo \"Fetching Copilot PRs from the last 30 days...\"\n gh pr list --repo \"$GITHUB_REPOSITORY\" \\\n --search \"head:copilot/ created:>=${DATE_30_DAYS_AGO}\" \\\n --state all \\\n --json number,title,author,headRefName,createdAt,state,url,body,labels,updatedAt,closedAt,mergedAt \\\n --limit 1000 \\\n > /tmp/gh-aw/agent/pr-data/copilot-prs.json\n\n # Generate schema for reference\n ./.github/skills/jqschema/jqschema.sh < /tmp/gh-aw/agent/pr-data/copilot-prs.json > /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\n\n # Store in cache with today's date\n cp /tmp/gh-aw/agent/pr-data/copilot-prs.json \"$CACHE_DIR/copilot-prs-${TODAY}.json\"\n cp /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\"\n\n echo \"✓ PR data saved to cache: copilot-prs-${TODAY}.json\"\n echo \"Total PRs found: $(jq 'length' /tmp/gh-aw/agent/pr-data/copilot-prs.json)\"\nfi\n\n# Always ensure data is available at expected locations for backward compatibility\necho \"PR data available at: /tmp/gh-aw/agent/pr-data/copilot-prs.json\"\necho \"Schema available at: /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\"\n" + - name: Token budget guard + run: "PROMPT_FILE=\"/tmp/gh-aw/aw-prompts/prompt.txt\"\nif [ -f \"$PROMPT_FILE\" ]; then\n PROMPT_CHARS=$(wc -c < \"$PROMPT_FILE\")\n ESTIMATED_TOKENS=$((PROMPT_CHARS / 4))\n if [ \"$ESTIMATED_TOKENS\" -gt 50000 ]; then\n echo \"::warning::First-turn token budget: ~${ESTIMATED_TOKENS} estimated tokens (${PROMPT_CHARS} chars) exceeds 50k threshold. Consider moving more phase details to skill blocks to reduce initial context.\"\n else\n echo \"First-turn token estimate: ~${ESTIMATED_TOKENS} tokens (${PROMPT_CHARS} chars) — within 50k budget.\"\n fi\nfi\n" + - name: Trim large session logs + run: "LOG_DIR=\"/tmp/gh-aw/agent/session-data/logs\"\nTHRESHOLD=10240\nif [ -d \"$LOG_DIR\" ]; then\n for f in \"$LOG_DIR\"/*; do\n if [ -f \"$f\" ]; then\n SIZE=$(wc -c < \"$f\")\n if [ \"$SIZE\" -gt \"$THRESHOLD\" ]; then\n STRIPPED=$(( (SIZE - 6144) / 1024 ))\n echo \"Trimming large session log: $f (${SIZE} bytes, stripping ~${STRIPPED}KB of boilerplate)\"\n { head -c 5120 \"$f\"; printf \"\\n...[%dKB stripped — fetch raw on demand if needed]\\n\" \"$STRIPPED\"; tail -c 1024 \"$f\"; } > \"${f}.trimmed\"\n mv \"${f}.trimmed\" \"$f\"\n fi\n fi\n done\nfi" - name: Configure Git credentials env: diff --git a/.github/workflows/copilot-opt.md b/.github/workflows/copilot-opt.md index 4ef00a43755..16b0df2a08f 100644 --- a/.github/workflows/copilot-opt.md +++ b/.github/workflows/copilot-opt.md @@ -59,6 +59,36 @@ evals: question: Did the agent analyze Copilot sessions from the last 14 days? - id: three_issues_created question: Were three optimization issues created with evidence-backed recommendations? +steps: + - name: Token budget guard + run: | + PROMPT_FILE="/tmp/gh-aw/aw-prompts/prompt.txt" + if [ -f "$PROMPT_FILE" ]; then + PROMPT_CHARS=$(wc -c < "$PROMPT_FILE") + ESTIMATED_TOKENS=$((PROMPT_CHARS / 4)) + if [ "$ESTIMATED_TOKENS" -gt 50000 ]; then + echo "::warning::First-turn token budget: ~${ESTIMATED_TOKENS} estimated tokens (${PROMPT_CHARS} chars) exceeds 50k threshold. Consider moving more phase details to skill blocks to reduce initial context." + else + echo "First-turn token estimate: ~${ESTIMATED_TOKENS} tokens (${PROMPT_CHARS} chars) — within 50k budget." + fi + fi + - name: Trim large session logs + run: | + LOG_DIR="/tmp/gh-aw/agent/session-data/logs" + THRESHOLD=10240 + if [ -d "$LOG_DIR" ]; then + for f in "$LOG_DIR"/*; do + if [ -f "$f" ]; then + SIZE=$(wc -c < "$f") + if [ "$SIZE" -gt "$THRESHOLD" ]; then + STRIPPED=$(( (SIZE - 6144) / 1024 )) + echo "Trimming large session log: $f (${SIZE} bytes, stripping ~${STRIPPED}KB of boilerplate)" + { head -c 5120 "$f"; printf "\n...[%dKB stripped — fetch raw on demand if needed]\n" "$STRIPPED"; tail -c 1024 "$f"; } > "${f}.trimmed" + mv "${f}.trimmed" "$f" + fi + fi + done + fi --- {{#runtime-import? .github/shared-instructions.md}} @@ -134,6 +164,60 @@ Use UTC for all time filtering. ## Phase 2 — Performance Analysis +Invoke skill `opt-phase-performance` for the full performance analysis procedure. Aggregate across all sessions to identify recurring systemic patterns. + +## Phase 3 — PR Cross-Analysis and Duplicate Pattern Detection + +This phase is **mandatory**. Invoke skill `opt-phase-pr-analysis` for the full PR cross-analysis and duplicate pattern detection procedure (including jq commands and the retry-blocked topics table). + +## Phase 4 — Recommendation Selection + +Produce exactly three recommendations ranked by impact. Invoke skill `opt-phase-recommendations` for the full selection rules, domains, and criteria. + +## Phase 5 — Issue Creation (Exactly Three) + +Create exactly three GitHub issues. Invoke skill `opt-phase-issue-creation` for the full issue template, retry-blocked addendum format, and label rules. + +## Items That Should Not Be Addressed + +The following items are out of scope because they are not actionable by repository users: + +- **Copilot-assigned branch naming conventions** (for example, `-again` / `-yet-again` suffixes) + - **Rationale:** Branch names are generated automatically by GitHub Copilot and are not user-configurable in this workflow context. + - **Rule:** Do not create recommendations or issues requesting changes to Copilot's auto-generated branch naming behavior. + +## Output Constraints + +- Do not generate implementation code or modify repository files. +- Do not create more or fewer than three issues. +- Keep findings grounded in analyzed data only. +- Keep recommendations non-overlapping and actionable. +- Do not create issues for items listed in **Items That Should Not Be Addressed**. + +## Final Validation Checklist + +Before creating issues, verify: + +- [ ] last-14-day filtering was applied +- [ ] `events.jsonl` parsing was attempted across all in-scope sessions +- [ ] tool latency/payload, validation timing, context size, orchestration, and prompt drift were analyzed +- [ ] Phase 3 PR cross-analysis was performed (not skipped) +- [ ] duplicate PR pattern detection was run and retry-blocked topics table was built +- [ ] retry-blocked topics (≥2 closed PRs) are reflected in at least one recommendation when present +- [ ] exactly three recommendations selected +- [ ] each recommendation has evidence + proposed change + expected impact +- [ ] retry-blocked issues include the "Prior Failed Attempts" addendum and `copilot-retry-blocked` label +- [ ] exactly three issue outputs will be created + +## Usage + +Run manually with `workflow_dispatch`, or let the weekly schedule generate a fresh optimization triage. + +## skill: `opt-phase-performance` +--- +description: Phase 2 — detailed per-session performance analysis procedure +--- + For each session summary: 1. Compute tool latency metrics and flag slow outliers. @@ -145,7 +229,10 @@ For each session summary: Aggregate across all sessions to identify recurring systemic patterns. -## Phase 3 — PR Cross-Analysis and Duplicate Pattern Detection +## skill: `opt-phase-pr-analysis` +--- +description: Phase 3 — PR cross-analysis and duplicate pattern detection procedure +--- This phase is **mandatory**. `/tmp/gh-aw/agent/pr-data/copilot-prs.json` is always present from the imported `shared/copilot-pr-data-fetch.md` step. @@ -193,7 +280,10 @@ For each topic with **two or more** closed-without-merge PRs (retry-blocked topi If PR data is unexpectedly unavailable (file missing or empty), skip Phase 3 and note that in all three issue bodies. -## Phase 4 — Recommendation Selection +## skill: `opt-phase-recommendations` +--- +description: Phase 4 — recommendation selection rules, domains, and criteria +--- Produce exactly three recommendations ranked by impact. @@ -214,7 +304,10 @@ Possible recommendation domains: - prompt design corrections to reduce drift - **duplicate-PR / retry waste reduction** (use when Phase 3b finds retry-blocked topics) -## Phase 5 — Issue Creation (Exactly Three) +## skill: `opt-phase-issue-creation` +--- +description: Phase 5 — issue creation template, retry-blocked addendum format, and label rules +--- Create exactly three issues with this structure: @@ -270,39 +363,4 @@ Any agent attempting to implement this recommendation MUST read this section and ### Labels for Retry-Blocked Issues -When creating an issue that covers a retry-blocked topic, add `copilot-retry-blocked` to the labels list in the `create_issue` safe-output call alongside the standard labels. - -## Items That Should Not Be Addressed - -The following items are out of scope because they are not actionable by repository users: - -- **Copilot-assigned branch naming conventions** (for example, `-again` / `-yet-again` suffixes) - - **Rationale:** Branch names are generated automatically by GitHub Copilot and are not user-configurable in this workflow context. - - **Rule:** Do not create recommendations or issues requesting changes to Copilot's auto-generated branch naming behavior. - -## Output Constraints - -- Do not generate implementation code or modify repository files. -- Do not create more or fewer than three issues. -- Keep findings grounded in analyzed data only. -- Keep recommendations non-overlapping and actionable. -- Do not create issues for items listed in **Items That Should Not Be Addressed**. - -## Final Validation Checklist - -Before creating issues, verify: - -- [ ] last-14-day filtering was applied -- [ ] `events.jsonl` parsing was attempted across all in-scope sessions -- [ ] tool latency/payload, validation timing, context size, orchestration, and prompt drift were analyzed -- [ ] Phase 3 PR cross-analysis was performed (not skipped) -- [ ] duplicate PR pattern detection was run and retry-blocked topics table was built -- [ ] retry-blocked topics (≥2 closed PRs) are reflected in at least one recommendation when present -- [ ] exactly three recommendations selected -- [ ] each recommendation has evidence + proposed change + expected impact -- [ ] retry-blocked issues include the "Prior Failed Attempts" addendum and `copilot-retry-blocked` label -- [ ] exactly three issue outputs will be created - -## Usage - -Run manually with `workflow_dispatch`, or let the weekly schedule generate a fresh optimization triage. \ No newline at end of file +When creating an issue that covers a retry-blocked topic, add `copilot-retry-blocked` to the labels list in the `create_issue` safe-output call alongside the standard labels. \ No newline at end of file From e6ef1a4419c832d8df7a505c5a4a03b954d959d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 05:23:53 +0000 Subject: [PATCH 3/3] =?UTF-8?q?fix(copilot-opt):=20address=20code=20review?= =?UTF-8?q?=20=E2=80=94=20REMOVED=5FKB,=20%d=20format,=20clarify=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename STRIPPED_KB → REMOVED_KB to clarify the variable represents removed content in KB - Use %d (integer) format specifier instead of %s for printf - Add comment explaining why overlap guard is unnecessary (THRESHOLD > FIRST_CHUNK+LAST_CHUNK) - Update token estimate comment to match divisor (3 chars/token conservative estimate) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/copilot-opt.lock.yml | 6 +++--- .github/workflows/copilot-opt.md | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/copilot-opt.lock.yml b/.github/workflows/copilot-opt.lock.yml index 05904a3119e..e33a5a15cf6 100644 --- a/.github/workflows/copilot-opt.lock.yml +++ b/.github/workflows/copilot-opt.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"10c827708e77b389be48817ce9266b917f70a55dd01ce4718cefad64c963551d","body_hash":"71b67df8a9f211ce9b8791cc06df67e553f5febed6b4b356550090e62c439b60","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.71","copilot-sdk":"1.0.7"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"08732e099fe9569e8a6720bcd34c21a3f2c8cc5fd6f7f05ad222128afa762a4c","body_hash":"71b67df8a9f211ce9b8791cc06df67e553f5febed6b4b356550090e62c439b60","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.71","copilot-sdk":"1.0.7"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37","digest":"sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37@sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37","digest":"sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37@sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.37","digest":"sha256:1d5300d9b08e1c4f2ad1830860656a0656383a83280058f17e805a7c3ecda203","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.37@sha256:1d5300d9b08e1c4f2ad1830860656a0656383a83280058f17e805a7c3ecda203"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37","digest":"sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37@sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.1","digest":"sha256:ad2a979c2cd8b50098e84938ca9c9c1580eb8e91526f101a90adfba7859b2c32","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.1@sha256:ad2a979c2cd8b50098e84938ca9c9c1580eb8e91526f101a90adfba7859b2c32"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.6.0","digest":"sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3","pinned_image":"ghcr.io/github/github-mcp-server:v1.6.0@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -533,9 +533,9 @@ jobs: name: Fetch Copilot PR data run: "# Create output directories\nmkdir -p /tmp/gh-aw/agent/pr-data\nmkdir -p /tmp/gh-aw/cache-memory\n\n# Get today's date for cache identification\nTODAY=$(date '+%Y-%m-%d')\nCACHE_DIR=\"/tmp/gh-aw/cache-memory\"\n\n# Check if cached data exists from today\nif [ -f \"$CACHE_DIR/copilot-prs-${TODAY}.json\" ] && [ -s \"$CACHE_DIR/copilot-prs-${TODAY}.json\" ]; then\n echo \"✓ Found cached PR data from ${TODAY}\"\n cp \"$CACHE_DIR/copilot-prs-${TODAY}.json\" /tmp/gh-aw/agent/pr-data/copilot-prs.json\n \n # Regenerate schema if missing\n if [ ! -f \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\" ]; then\n ./.github/skills/jqschema/jqschema.sh < /tmp/gh-aw/agent/pr-data/copilot-prs.json > \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\"\n fi\n cp \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\" /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\n \n echo \"Using cached data from ${TODAY}\"\n echo \"Total PRs in cache: $(jq 'length' /tmp/gh-aw/agent/pr-data/copilot-prs.json)\"\nelse\n echo \"⬇ Downloading fresh PR data...\"\n \n # Calculate date 30 days ago\n DATE_30_DAYS_AGO=$(date -d '30 days ago' '+%Y-%m-%d' 2>/dev/null || date -v-30d '+%Y-%m-%d')\n\n # Search for PRs from copilot/* branches in the last 30 days using gh CLI\n # Using branch prefix search (head:copilot/) instead of author for reliability\n echo \"Fetching Copilot PRs from the last 30 days...\"\n gh pr list --repo \"$GITHUB_REPOSITORY\" \\\n --search \"head:copilot/ created:>=${DATE_30_DAYS_AGO}\" \\\n --state all \\\n --json number,title,author,headRefName,createdAt,state,url,body,labels,updatedAt,closedAt,mergedAt \\\n --limit 1000 \\\n > /tmp/gh-aw/agent/pr-data/copilot-prs.json\n\n # Generate schema for reference\n ./.github/skills/jqschema/jqschema.sh < /tmp/gh-aw/agent/pr-data/copilot-prs.json > /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\n\n # Store in cache with today's date\n cp /tmp/gh-aw/agent/pr-data/copilot-prs.json \"$CACHE_DIR/copilot-prs-${TODAY}.json\"\n cp /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json \"$CACHE_DIR/copilot-prs-${TODAY}-schema.json\"\n\n echo \"✓ PR data saved to cache: copilot-prs-${TODAY}.json\"\n echo \"Total PRs found: $(jq 'length' /tmp/gh-aw/agent/pr-data/copilot-prs.json)\"\nfi\n\n# Always ensure data is available at expected locations for backward compatibility\necho \"PR data available at: /tmp/gh-aw/agent/pr-data/copilot-prs.json\"\necho \"Schema available at: /tmp/gh-aw/agent/pr-data/copilot-prs-schema.json\"\n" - name: Token budget guard - run: "PROMPT_FILE=\"/tmp/gh-aw/aw-prompts/prompt.txt\"\nif [ -f \"$PROMPT_FILE\" ]; then\n PROMPT_CHARS=$(wc -c < \"$PROMPT_FILE\")\n ESTIMATED_TOKENS=$((PROMPT_CHARS / 4))\n if [ \"$ESTIMATED_TOKENS\" -gt 50000 ]; then\n echo \"::warning::First-turn token budget: ~${ESTIMATED_TOKENS} estimated tokens (${PROMPT_CHARS} chars) exceeds 50k threshold. Consider moving more phase details to skill blocks to reduce initial context.\"\n else\n echo \"First-turn token estimate: ~${ESTIMATED_TOKENS} tokens (${PROMPT_CHARS} chars) — within 50k budget.\"\n fi\nfi\n" + run: "PROMPT_FILE=\"/tmp/gh-aw/aw-prompts/prompt.txt\"\nif [ -f \"$PROMPT_FILE\" ]; then\n PROMPT_CHARS=$(wc -c < \"$PROMPT_FILE\")\n # Conservative approximation: ~3 chars/token (technical content)\n ESTIMATED_TOKENS=$((PROMPT_CHARS / 3))\n if [ \"$ESTIMATED_TOKENS\" -gt 50000 ]; then\n echo \"::warning::First-turn token budget: ~${ESTIMATED_TOKENS} estimated tokens (${PROMPT_CHARS} chars) exceeds 50k threshold. Consider moving more phase details to skill blocks to reduce initial context.\"\n else\n echo \"First-turn token estimate: ~${ESTIMATED_TOKENS} tokens (${PROMPT_CHARS} chars) — within 50k budget.\"\n fi\nfi\n" - name: Trim large session logs - run: "LOG_DIR=\"/tmp/gh-aw/agent/session-data/logs\"\nTHRESHOLD=10240\nif [ -d \"$LOG_DIR\" ]; then\n for f in \"$LOG_DIR\"/*; do\n if [ -f \"$f\" ]; then\n SIZE=$(wc -c < \"$f\")\n if [ \"$SIZE\" -gt \"$THRESHOLD\" ]; then\n STRIPPED=$(( (SIZE - 6144) / 1024 ))\n echo \"Trimming large session log: $f (${SIZE} bytes, stripping ~${STRIPPED}KB of boilerplate)\"\n { head -c 5120 \"$f\"; printf \"\\n...[%dKB stripped — fetch raw on demand if needed]\\n\" \"$STRIPPED\"; tail -c 1024 \"$f\"; } > \"${f}.trimmed\"\n mv \"${f}.trimmed\" \"$f\"\n fi\n fi\n done\nfi" + run: "LOG_DIR=\"/tmp/gh-aw/agent/session-data/logs\"\nTHRESHOLD=10240\nFIRST_CHUNK=5120\nLAST_CHUNK=1024\nif [ -d \"$LOG_DIR\" ]; then\n for f in \"$LOG_DIR\"/*; do\n if [ -f \"$f\" ]; then\n SIZE=$(wc -c < \"$f\")\n if [ \"$SIZE\" -gt \"$THRESHOLD\" ]; then\n # THRESHOLD (10240) > FIRST_CHUNK+LAST_CHUNK (6144), so no chunk overlap possible\n REMOVED_KB=$(( (SIZE - FIRST_CHUNK - LAST_CHUNK) / 1024 ))\n echo \"Trimming large session log: $f (${SIZE} bytes, stripping ~${REMOVED_KB}KB of boilerplate)\"\n { head -c \"$FIRST_CHUNK\" \"$f\"; printf \"...[%dKB stripped — fetch raw on demand if needed]\\n\" \"$REMOVED_KB\"; tail -c \"$LAST_CHUNK\" \"$f\"; } > \"${f}.trimmed\"\n mv \"${f}.trimmed\" \"$f\"\n fi\n fi\n done\nfi" - name: Configure Git credentials env: diff --git a/.github/workflows/copilot-opt.md b/.github/workflows/copilot-opt.md index 16b0df2a08f..c4848bdacb7 100644 --- a/.github/workflows/copilot-opt.md +++ b/.github/workflows/copilot-opt.md @@ -65,7 +65,8 @@ steps: PROMPT_FILE="/tmp/gh-aw/aw-prompts/prompt.txt" if [ -f "$PROMPT_FILE" ]; then PROMPT_CHARS=$(wc -c < "$PROMPT_FILE") - ESTIMATED_TOKENS=$((PROMPT_CHARS / 4)) + # Conservative approximation: ~3 chars/token (technical content) + ESTIMATED_TOKENS=$((PROMPT_CHARS / 3)) if [ "$ESTIMATED_TOKENS" -gt 50000 ]; then echo "::warning::First-turn token budget: ~${ESTIMATED_TOKENS} estimated tokens (${PROMPT_CHARS} chars) exceeds 50k threshold. Consider moving more phase details to skill blocks to reduce initial context." else @@ -76,14 +77,17 @@ steps: run: | LOG_DIR="/tmp/gh-aw/agent/session-data/logs" THRESHOLD=10240 + FIRST_CHUNK=5120 + LAST_CHUNK=1024 if [ -d "$LOG_DIR" ]; then for f in "$LOG_DIR"/*; do if [ -f "$f" ]; then SIZE=$(wc -c < "$f") if [ "$SIZE" -gt "$THRESHOLD" ]; then - STRIPPED=$(( (SIZE - 6144) / 1024 )) - echo "Trimming large session log: $f (${SIZE} bytes, stripping ~${STRIPPED}KB of boilerplate)" - { head -c 5120 "$f"; printf "\n...[%dKB stripped — fetch raw on demand if needed]\n" "$STRIPPED"; tail -c 1024 "$f"; } > "${f}.trimmed" + # THRESHOLD (10240) > FIRST_CHUNK+LAST_CHUNK (6144), so no chunk overlap possible + REMOVED_KB=$(( (SIZE - FIRST_CHUNK - LAST_CHUNK) / 1024 )) + echo "Trimming large session log: $f (${SIZE} bytes, stripping ~${REMOVED_KB}KB of boilerplate)" + { head -c "$FIRST_CHUNK" "$f"; printf "...[%dKB stripped — fetch raw on demand if needed]\n" "$REMOVED_KB"; tail -c "$LAST_CHUNK" "$f"; } > "${f}.trimmed" mv "${f}.trimmed" "$f" fi fi