# ENTERPRISE_SETUP.md — Enterprise & Team Setup Guide > This guide covers GitHub Enterprise API integration for tracking Copilot acceptance rates, > CI pipeline setup with structured JSON reporting, usage log analysis for teams, and > self-hosted runner configuration. --- ## Overview SigMap ships three observability features from v0.9: | Feature | Command | Output | |---|---|---| | JSON token report | `--report --json` | Structured JSON, exits 1 if over budget | | Usage log | `--track` or `config.tracking: true` | `.context/usage.ndjson` | | Usage history | `--report --history` | Aggregate stats from usage log | --- ## 1 — CI token reporting (`--report --json`) ### What it outputs ```json { "version": "6.5.0", "timestamp": "2026-04-01T00:00:00.000Z", "rawTokens": 42000, "finalTokens": 3200, "fileCount": 147, "droppedCount": 12, "reductionPct": 92.4, "overBudget": false, "budgetLimit": 6000 } ``` ### Exit codes | Condition | Exit code | |---|---| | Output within budget | `0` | | Output exceeds `maxTokens` | `1` | This lets CI pipelines fail automatically if context bloat is detected. ### GitHub Actions integration ```yaml # .github/workflows/context.yml name: Context freshness on: [push, pull_request] jobs: context: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Use Node.js 20 uses: actions/setup-node@v4 with: node-version: '20' - name: Generate context run: node gen-context.js --format cache - name: Token report (JSON, fail if over budget) id: report run: | REPORT=$(node gen-context.js --report --json) echo "report=$REPORT" >> "$GITHUB_OUTPUT" # Exit 1 if overBudget=true (gen-context.js sets exit code automatically) - name: Upload context artifact uses: actions/upload-artifact@v4 with: name: sigmap-output path: | .github/copilot-instructions.md .github/copilot-instructions.cache.json ``` ### Parsing the JSON report in CI ```bash # In a shell step — check reduction and fail if below threshold REPORT=$(node gen-context.js --report --json) REDUCTION=$(echo "$REPORT" | node -e "process.stdin.resume(); let d=''; process.stdin.on('data',c=>d+=c); process.stdin.on('end',()=>console.log(JSON.parse(d).reductionPct))") if (( $(echo "$REDUCTION < 60" | bc -l) )); then echo "Context reduction below 60% — context may need cleanup" exit 1 fi ``` --- ## 2 — Usage log (`--track`) ### Enable tracking **CLI flag (one-time):** ```bash node gen-context.js --track ``` **Config (permanent):** ```json { "tracking": true } ``` Once enabled, every `node gen-context.js` run appends one JSON line to `.context/usage.ndjson`. ### Log format (NDJSON) Each line is one record: ```json {"ts":"2026-04-01T09:00:00.000Z","version":"6.5.0","fileCount":147,"droppedCount":0,"rawTokens":42000,"finalTokens":3200,"reductionPct":92.4,"overBudget":false,"budgetLimit":6000} {"ts":"2026-04-01T09:30:00.000Z","version":"6.5.0","fileCount":149,"droppedCount":2,"rawTokens":43500,"finalTokens":3400,"reductionPct":92.2,"overBudget":false,"budgetLimit":6000} ``` Because it's NDJSON (one JSON object per line), it's easy to process with standard tools: ```bash # Count total runs wc -l .context/usage.ndjson # Average final token count node -e " const lines = require('fs').readFileSync('.context/usage.ndjson','utf8').trim().split('\n'); const entries = lines.map(l => JSON.parse(l)); const avg = entries.reduce((s,e) => s + e.finalTokens, 0) / entries.length; console.log('avg final tokens:', Math.round(avg)); " # Find any over-budget runs grep '"overBudget":true' .context/usage.ndjson ``` ### View summary ```bash node gen-context.js --report --history # [sigmap] usage history: # total runs : 42 # avg reduction : 91.8% # avg tokens out : ~3280 # over-budget runs: 0 # first run : 2026-03-01T08:00:00.000Z # last run : 2026-04-01T09:30:00.000Z # JSON output for dashboards: node gen-context.js --report --history --json ``` ### Commit the log or ignore it To track history across the team, commit the log: ```bash # .gitignore — make sure .context/ is NOT ignored if you want shared history # .context/usage.ndjson ← remove this line if present ``` To keep it local: ```gitignore .context/usage.ndjson ``` --- ## 3 — GitHub Enterprise acceptance rate tracking GitHub Enterprise provides Copilot suggestion acceptance rates via the REST API. Use this to measure whether SigMap is actually improving suggestions. ### Get acceptance rate via API ```bash # Requires: GitHub Enterprise Cloud, Copilot Business/Enterprise license # Token scope: manage_billing:copilot or read:enterprise curl -s \ -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/enterprises/{enterprise}/copilot/usage" \ | node -e " process.stdin.resume(); let d = ''; process.stdin.on('data', c => d += c); process.stdin.on('end', () => { const data = JSON.parse(d); // Sum suggestions and acceptances across all days let totalSuggestions = 0, totalAcceptances = 0; for (const day of data) { totalSuggestions += day.total_suggestions_count || 0; totalAcceptances += day.total_acceptances_count || 0; } const rate = totalSuggestions > 0 ? ((totalAcceptances / totalSuggestions) * 100).toFixed(1) : 0; console.log(JSON.stringify({ totalSuggestions, totalAcceptances, acceptanceRate: rate + '%' })); }); " ``` ### Acceptance rate targets | Scenario | Expected rate | |---|---| | Without SigMap | ~26% | | With SigMap (fresh context) | ≥32% | | With SigMap + stale context (>1 week) | ~28% | If the rate drops below 30%, run `node gen-context.js` to regenerate context. ### CI acceptance gate Add a weekly job to check acceptance rate and fail if below threshold: ```yaml # .github/workflows/copilot-acceptance.yml name: Copilot acceptance rate check on: schedule: - cron: '0 9 * * 1' # every Monday at 9am jobs: check-acceptance: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check Copilot acceptance rate env: GITHUB_TOKEN: ${{ secrets.COPILOT_METRICS_TOKEN }} ENTERPRISE: ${{ vars.GITHUB_ENTERPRISE_SLUG }} run: | node -e " const https = require('https'); const options = { hostname: 'api.github.com', path: '/enterprises/${{ vars.GITHUB_ENTERPRISE_SLUG }}/copilot/usage', headers: { 'Authorization': 'Bearer ' + process.env.GITHUB_TOKEN, 'Accept': 'application/vnd.github+json', 'User-Agent': 'sigmap-ci' } }; https.get(options, (res) => { let data = ''; res.on('data', c => data += c); res.on('end', () => { const days = JSON.parse(data); const total = days.reduce((s,d) => ({ s: s.s + (d.total_suggestions_count||0), a: s.a + (d.total_acceptances_count||0) }), { s: 0, a: 0 }); const rate = total.s > 0 ? (total.a / total.s) * 100 : 0; console.log('Acceptance rate:', rate.toFixed(1) + '%'); if (rate < 30) { console.error('Below 30% threshold — regenerate context'); process.exit(1); } }); }); " - name: Regenerate context if needed if: failure() run: node gen-context.js ``` --- ## 4 — Self-hosted runner configuration For air-gapped or on-premise environments: ```bash # Install on self-hosted runner (no npm needed) git clone https://github.com/your-org/sigmap /opt/sigmap # Or copy just gen-context.js to the project # Add to runner environment echo 'alias gen-context="node /opt/sigmap/gen-context.js"' >> ~/.bashrc # Pre-commit hook (global git config) git config --global core.hooksPath /opt/git-hooks cat > /opt/git-hooks/post-commit << 'EOF' #!/bin/sh node "$(git rev-parse --show-toplevel)/gen-context.js" --generate 2>/dev/null || true EOF chmod +x /opt/git-hooks/post-commit ``` --- ## 5 — Team dashboard (Prometheus + Grafana) The `--report --json` output can be scraped into any time-series database. ### Push metrics to Prometheus Pushgateway ```bash # In your CI step (after generating context) REPORT=$(node gen-context.js --report --json) FINAL_TOKENS=$(echo "$REPORT" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).finalTokens))") REDUCTION=$(echo "$REPORT" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).reductionPct))") cat <d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).score))") echo "Health score: $SCORE/100" if [ "$SCORE" -lt 60 ]; then echo "Health score below 60 — context may need attention" exit 1 fi ``` ### Self-healing CI Copy `examples/self-healing-github-action.yml` to `.github/workflows/` to automatically open a PR when: - Copilot acceptance rate drops below 30% (requires `COPILOT_API_TOKEN` secret) - Context file is older than 7 days (always active, no API needed) See [examples/self-healing-github-action.yml](../examples/self-healing-github-action.yml) for the full workflow. --- ## Related docs - [docs/REPOMIX_CACHE.md](REPOMIX_CACHE.md) — prompt cache cost reduction - [docs/MODEL_ROUTING.md](MODEL_ROUTING.md) — model tier routing + `--suggest-tool` - [docs/MCP_SETUP.md](MCP_SETUP.md) — MCP server configuration - [docs/CI_GUIDE.md](CI_GUIDE.md) — CI integration and monorepo setup - [docs/SESSION_DISCIPLINE.md](SESSION_DISCIPLINE.md) — session workflow > *SigMap for daily always-on context; Repomix for deep one-off sessions — use both.*