Skip to content

⚡ Copilot Token Optimization2026-06-30 — Test Coverage Improver #5715

Description

@github-actions

Target Workflow: test-coverage-improver

Source report: #5714
Estimated cost per run: N/A (token telemetry absent — AIC proxy used)
AIC per run: 304.1 (highest in report)
Actions minutes/run: 20.0 min
GitHub API calls/run: 10
Model: claude-haiku-4-5
Runs analyzed: 1 (2026-06-30)

⚠️ Token telemetry is absent for all runs in the report. AIC (Actions Intelligence Credits) is used as the proxy signal. Recommendations focus on reducing LLM input token volume based on static prompt analysis.

Current Configuration

Setting Value
Model claude-haiku-4-5
GitHub toolsets [repos] ✅ (already restricted)
Network groups [github] ✅ (minimal)
Bash tools Restricted to node:*, jest, eslint, cat:jest.config.*
Pre-agent steps Yes — npm ci, build, coverage run, file injection
Turn budget ≤ 6 tool calls (explicit instruction) ✅
Prompt body size ~3,120 chars (~780 tokens)
COVERAGE_SUMMARY.md injection 4,356 chars (~1,089 tokens) ⚠️
Existing test file injection up to 25,254 chars (~6,313 tokens) ⚠️

Recommendations

1. Truncate the existing test file injection to the first 100 lines

Estimated savings: ~2,800–5,500 tokens/run (~15–25% of estimated total input)

The Select target file and inject content step injects the entire existing test file into the prompt for style reference. When a well-covered target is selected, this can be enormous:

Test file Lines Est. tokens
src/domain-patterns.test.ts 591 ~6,313
src/cli.test.ts 383 ~3,560
src/docker-manager.test.ts not found ~0

The agent only needs the first 100 lines (import setup, mock patterns, first few describe blocks) to infer style — not the full file.

Change in .github/workflows/test-coverage-improver.md, step Select target file and inject content:

-      TEST_FILE="${TARGET%.ts}.test.ts"
-      echo "TARGET_TEST_FILE=$TEST_FILE" >> "$GITHUB_OUTPUT"
-      {
-        echo "TEST_CONTENT<<EOF"
-        cat "$TEST_FILE" 2>/dev/null || echo "(test file does not exist yet)"
-        echo "EOF"
-      } >> "$GITHUB_OUTPUT"
+      TEST_FILE="${TARGET%.ts}.test.ts"
+      echo "TARGET_TEST_FILE=$TEST_FILE" >> "$GITHUB_OUTPUT"
+      {
+        echo "TEST_CONTENT<<EOF"
+        if [ -f "$TEST_FILE" ]; then
+          LINE_COUNT=$(wc -l < "$TEST_FILE")
+          head -100 "$TEST_FILE"
+          if [ "$LINE_COUNT" -gt 100 ]; then
+            echo ""
+            echo "// ... ($((LINE_COUNT - 100)) more lines truncated for brevity — file exists at $TEST_FILE)"
+          fi
+        else
+          echo "(test file does not exist yet)"
+        fi
+        echo "EOF"
+      } >> "$GITHUB_OUTPUT"

2. Replace COVERAGE_SUMMARY.md injection with a minimal fresh table

Estimated savings: ~850 tokens/run (~5–8% of estimated total input)

The step Read COVERAGE_SUMMARY.md reads the static COVERAGE_SUMMARY.md file (4,356 bytes). This file is a stale artifact from a previous PR containing irrelevant sections: "Coverage Improvements in This PR", "Before/After comparisons", "Integration with CI/CD", "How to View Coverage" docs, etc. The agent only needs current per-file coverage percentages.

The run already generates coverage/coverage-summary.json in the Run coverage step. Use it directly for a concise table:

Change in .github/workflows/test-coverage-improver.md, replace the Read COVERAGE_SUMMARY.md step:

-  - name: Read COVERAGE_SUMMARY.md
-    id: coverage-md
-    run: |
-      {
-        echo "COVERAGE_MD<<EOF"
-        cat COVERAGE_SUMMARY.md 2>/dev/null || echo "(COVERAGE_SUMMARY.md not found)"
-        echo "EOF"
-      } >> "$GITHUB_OUTPUT"
+  - name: Generate compact coverage table
+    id: coverage-md
+    run: |
+      {
+        echo "COVERAGE_MD<<EOF"
+        node -e "
+          const d = JSON.parse(require('fs').readFileSync('coverage/coverage-summary.json','utf8'));
+          const t = d.total;
+          console.log('Overall: stmts=' + t.statements.pct + '%, branches=' + t.branches.pct + '%, fns=' + t.functions.pct + '%, lines=' + t.lines.pct + '%');
+          console.log('');
+          console.log('| File | Stmts | Branches | Fns | Lines |');
+          console.log('|------|-------|----------|-----|-------|');
+          Object.entries(d).filter(([k]) => k !== 'total').forEach(([k,v]) => {
+            const f = k.split('/').pop();
+            console.log('| ' + f + ' | ' + v.statements.pct + '% | ' + v.branches.pct + '% | ' + v.functions.pct + '% | ' + v.lines.pct + '% |');
+          });
+        " 2>/dev/null || echo "(coverage summary not available)"
+        echo "EOF"
+      } >> "$GITHUB_OUTPUT"

This produces ~400 bytes instead of 4,356 bytes — a ~90% reduction for this injection alone.

3. Update the priority target list to actual implementation files

Estimated savings: Qualitative — improves work relevance, reduces wasted agent turns

The priority list points to re-export stubs:

Priority file Size Content
src/docker-manager.ts 577 B Re-exports from host-env, config-writer, container-lifecycle, container-cleanup
src/cli.ts 425 B 13-line entry point importing cli-options and commands/main-action
src/host-iptables.ts 415 B (re-export or small stub)

Writing tests for 577-byte re-export files provides minimal coverage value. The agent spends turns discovering this and pivoting. The actual uncovered implementations are:

Actual implementation Size Priority
src/container-lifecycle.ts 14,113 B High
src/config-writer.ts 12,452 B High
src/compose-generator.ts 13,498 B High
src/cli-options.ts 17,296 B Medium

Change in .github/workflows/test-coverage-improver.md, step Select target file and inject content:

-        const priority = ['src/docker-manager.ts','src/cli.ts','src/host-iptables.ts','src/squid-config.ts','src/domain-patterns.ts'];
+        const priority = [
+          'src/container-lifecycle.ts',
+          'src/config-writer.ts',
+          'src/compose-generator.ts',
+          'src/artifact-preservation.ts',
+          'src/github-env.ts',
+        ];

⚠️ Note: The source files for these targets are 12–17 KB each. When injecting the full file (via SOURCE_CONTENT), this adds ~3,000–4,300 tokens per run. Consider truncating source injection too (to 300 lines) for very large files, with a note that the agent can cat for the rest.

4. Trim verbose "Repository Context" section from prompt body

Estimated savings: ~200 tokens/run (~1–2%)

The "Repository Context" section in the prompt body restates general project knowledge the model already has from the system context. It can be reduced to one sentence:

-## Repository Context
-
-This is **gh-aw-firewall**, a network firewall for GitHub Copilot CLI that provides L7 (HTTP/HTTPS) egress control using Squid proxy and Docker containers. As a security-critical tool, comprehensive test coverage is essential for:
-
-- **iptables manipulation** - NET_ADMIN capability usage
-- **Squid ACL rules** - Domain pattern validation and filtering
-- **Container security** - Capability dropping, seccomp profiles
-- **Domain validation** - Pattern matching and injection prevention
+## Repository Context
+
+This is **gh-aw-firewall** — an L7 firewall for Copilot CLI using Squid + Docker. Security-critical paths: iptables rules, Squid ACL, container capabilities, domain validation.

Expected Impact

Metric Current Projected Savings
AIC/run 304.1 ~220–250 (est.) ~15–25%
Test file injection tokens 0–6,313 0–750 ~2,800–5,500
Coverage summary tokens ~1,089 ~100 ~989
Actions minutes/run 20.0 min ~18–20 min ~10% (less agent time)
Estimated cost/run N/A (no telemetry) N/A N/A

i️ Actual savings depend on which target file is selected each run. Recommendation #1 (test file truncation) has the highest variance but also highest ceiling.

Implementation Checklist


Generated by Daily Copilot Token Optimization Advisor · Source report: #5714

Generated by Daily Copilot Token Optimization Advisor · 58 AIC · ⊞ 6.7K ·

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions