Skip to content

Latest commit

 

History

History
376 lines (292 loc) · 10.9 KB

File metadata and controls

376 lines (292 loc) · 10.9 KB

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

{
  "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

# .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

# 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):

node gen-context.js --track

Config (permanent):

{
  "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:

{"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:

# 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

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:

# .gitignore — make sure .context/ is NOT ignored if you want shared history
# .context/usage.ndjson  ← remove this line if present

To keep it local:

.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

# 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:

# .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:

# 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

# 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 <<PROM | curl --data-binary @- http://pushgateway:9091/metrics/job/sigmap
# TYPE context_forge_final_tokens gauge
context_forge_final_tokens{repo="${GITHUB_REPOSITORY}"} ${FINAL_TOKENS}
# TYPE context_forge_reduction_pct gauge
context_forge_reduction_pct{repo="${GITHUB_REPOSITORY}"} ${REDUCTION}
PROM

6 — Health score & self-healing CI (v1.0)

Check installation health

node gen-context.js --health
# score           : 95/100 (grade A)
# token reduction : 91.2%
# days since regen: 1
# total runs      : 47
# over-budget runs: 0

# Machine-readable for CI:
node gen-context.js --health --json
# {"score":95,"grade":"A","tokenReductionPct":91.2,"daysSinceRegen":1,"totalRuns":47,"overBudgetRuns":0}

Add a health gate to CI to catch degradation early:

- name: SigMap health check
  run: |
    HEALTH=$(node gen-context.js --health --json)
    SCORE=$(echo "$HEALTH" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>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 for the full workflow.


Related docs

SigMap for daily always-on context; Repomix for deep one-off sessions — use both.