|
| 1 | +# Self-Hosting DiffScope |
| 2 | + |
| 3 | +This guide covers the server deployment path for DiffScope when you want persistent reviews, analytics artifacts, trend history, and operational diagnostics. |
| 4 | + |
| 5 | +## Recommended deployment path |
| 6 | + |
| 7 | +- Use the Helm chart in `charts/diffscope/` for long-running server deployments. |
| 8 | +- Use `docker-compose.yml` for local CLI + Ollama workflows only. The compose file runs `diffscope review`, not `diffscope serve`. |
| 9 | +- The container image itself defaults to `serve`, so Kubernetes/Helm is the intended self-hosted server path. |
| 10 | + |
| 11 | +## Minimum server checklist |
| 12 | + |
| 13 | +1. Mount a persistent volume at `/home/diffscope/.local/share/diffscope`. |
| 14 | +2. Keep the working tree at `/workspace` when you want server-side Git and PR workflows. |
| 15 | +3. Set a shared API key with `DIFFSCOPE_SERVER_API_KEY` for protected mutation routes. |
| 16 | +4. Point every persisted analytics artifact into the mounted data directory. |
| 17 | +5. Schedule `diffscope eval` and `diffscope feedback-eval` if you want trend charts to stay fresh. |
| 18 | + |
| 19 | +## Persistent artifact layout |
| 20 | + |
| 21 | +The server persists and reads these files during normal operation: |
| 22 | + |
| 23 | +| Purpose | Default path | Recommendation for Helm | |
| 24 | +| --- | --- | --- | |
| 25 | +| Review/event storage | `~/.local/share/diffscope/reviews.json` | keep default | |
| 26 | +| Learned conventions | `~/.local/share/diffscope/conventions.json` | keep default | |
| 27 | +| Feedback store | `.diffscope.feedback.json` | move under `/home/diffscope/.local/share/diffscope/feedback.json` | |
| 28 | +| Eval trend history | `.diffscope.eval-trend.json` | move under `/home/diffscope/.local/share/diffscope/eval-trend.json` | |
| 29 | +| Feedback-eval trend history | `.diffscope.feedback-eval-trend.json` | move under `/home/diffscope/.local/share/diffscope/feedback-eval-trend.json` | |
| 30 | +| Production replay pack | `~/.local/share/diffscope/eval/production_replay/replay.json` | keep default | |
| 31 | +| Failure forensics bundles | `~/.local/share/diffscope/forensics/...` | keep default | |
| 32 | + |
| 33 | +The Helm PVC only covers `/home/diffscope/.local/share/diffscope`, so the relative default paths for `feedback_path`, `eval_trend_path`, and `feedback_eval_trend_path` are not durable unless you override them. |
| 34 | + |
| 35 | +## Example Helm config |
| 36 | + |
| 37 | +```yaml |
| 38 | +diffscope: |
| 39 | + model: claude-opus-4-6 |
| 40 | + adapter: anthropic |
| 41 | + baseUrl: https://api.anthropic.com |
| 42 | + |
| 43 | +gitRepo: |
| 44 | + enabled: true |
| 45 | + repository: https://github.com/your-org/your-repo.git |
| 46 | + branch: main |
| 47 | + |
| 48 | +persistence: |
| 49 | + enabled: true |
| 50 | + size: 20Gi |
| 51 | + |
| 52 | +config: |
| 53 | + configFile: | |
| 54 | + model: claude-opus-4-6 |
| 55 | + model_reasoning: openai/o3 |
| 56 | + providers: |
| 57 | + anthropic: |
| 58 | + enabled: true |
| 59 | + openrouter: |
| 60 | + enabled: true |
| 61 | + feedback_path: /home/diffscope/.local/share/diffscope/feedback.json |
| 62 | + eval_trend_path: /home/diffscope/.local/share/diffscope/eval-trend.json |
| 63 | + feedback_eval_trend_path: /home/diffscope/.local/share/diffscope/feedback-eval-trend.json |
| 64 | + retention: |
| 65 | + review_max_age_days: 30 |
| 66 | + review_max_count: 1000 |
| 67 | + eval_artifact_max_age_days: 30 |
| 68 | + trend_history_max_entries: 200 |
| 69 | +
|
| 70 | + extraEnv: |
| 71 | + DIFFSCOPE_SERVER_API_KEY: ${DIFFSCOPE_SERVER_API_KEY} |
| 72 | + ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} |
| 73 | + OPENROUTER_API_KEY: ${OPENROUTER_API_KEY} |
| 74 | +``` |
| 75 | +
|
| 76 | +Notes: |
| 77 | +
|
| 78 | +- `providers.<name>.api_key` and provider-specific environment variables are the recommended way to run mixed-provider installs. |
| 79 | +- `openai/o3` and other non-Anthropic `vendor/model` ids route through OpenRouter unless you explicitly force another adapter. |
| 80 | +- `config.configFile` is mounted at `/workspace/.diffscope.yml`; it is easiest to use with `gitRepo.enabled: true` so the working directory already matches `/workspace`. |
| 81 | + |
| 82 | +## Secret-management guidance |
| 83 | + |
| 84 | +For enterprise installs, prefer external secret injection over storing credentials in `.diffscope.yml`. |
| 85 | + |
| 86 | +### Recommended secret sources |
| 87 | + |
| 88 | +- `ANTHROPIC_API_KEY` |
| 89 | +- `OPENAI_API_KEY` |
| 90 | +- `OPENROUTER_API_KEY` |
| 91 | +- `DIFFSCOPE_SERVER_API_KEY` |
| 92 | +- `GITHUB_TOKEN` |
| 93 | +- `DIFFSCOPE_GITHUB_APP_ID` |
| 94 | +- `DIFFSCOPE_GITHUB_PRIVATE_KEY` |
| 95 | +- `DIFFSCOPE_JIRA_BASE_URL` |
| 96 | +- `DIFFSCOPE_JIRA_EMAIL` |
| 97 | +- `DIFFSCOPE_JIRA_API_TOKEN` |
| 98 | +- `DIFFSCOPE_LINEAR_API_KEY` |
| 99 | + |
| 100 | +### Validation behavior |
| 101 | + |
| 102 | +`diffscope doctor`, the server doctor endpoint, and startup warnings now surface configuration issues for: |
| 103 | + |
| 104 | +- mixed-provider installs that still rely on legacy top-level `api_key` / `base_url` / `adapter` |
| 105 | +- missing provider-specific API keys for selected cloud providers |
| 106 | +- incomplete GitHub App config (`github_app_id` + `github_private_key` must be paired) |
| 107 | +- incomplete Jira config (`jira_base_url`, `jira_email`, `jira_api_token` must be paired) |
| 108 | +- incomplete Vault config (`vault_addr`, `vault_path`, `vault_token`) |
| 109 | + |
| 110 | +### Vault caveat |
| 111 | + |
| 112 | +Vault currently resolves only the legacy top-level `api_key`. For multi-provider installs, use provider-specific secrets from your runtime environment or secret store injection. |
| 113 | + |
| 114 | +## Analytics and retention |
| 115 | + |
| 116 | +### What populates Analytics |
| 117 | + |
| 118 | +- `/api/events` and `/api/events/stats` come from stored reviews and wide events. |
| 119 | +- `/api/analytics/learned-rules` reads the convention store. |
| 120 | +- `/api/analytics/rejected-patterns` reads the feedback store. |
| 121 | +- `/api/analytics/trends` and `/api/analytics/attention-gaps` read the eval and feedback-eval trend JSON files. |
| 122 | + |
| 123 | +### How to keep trend data fresh |
| 124 | + |
| 125 | +Run these on a schedule against a persisted artifact directory: |
| 126 | + |
| 127 | +```bash |
| 128 | +diffscope eval --fixtures eval/fixtures --artifact-dir /var/lib/diffscope/eval |
| 129 | +diffscope feedback-eval --input /home/diffscope/.local/share/diffscope/reviews.json --eval-report /var/lib/diffscope/eval/report.json |
| 130 | +``` |
| 131 | + |
| 132 | +### Retention controls |
| 133 | + |
| 134 | +- `retention.review_max_age_days` |
| 135 | +- `retention.review_max_count` |
| 136 | +- `retention.eval_artifact_max_age_days` |
| 137 | +- `retention.trend_history_max_entries` |
| 138 | + |
| 139 | +Completed reviews apply review retention automatically. Eval artifact pruning happens when you run `diffscope eval --artifact-dir ...`. |
| 140 | + |
| 141 | +### Analytics recompute job |
| 142 | + |
| 143 | +Use these protected endpoints after scoring or schema changes: |
| 144 | + |
| 145 | +```text |
| 146 | +POST /api/analytics/recompute |
| 147 | +GET /api/analytics/recompute/{job_id} |
| 148 | +``` |
| 149 | + |
| 150 | +The recompute job refreshes stored review summaries and event aggregates. It does not rebuild eval or feedback-eval trend files. |
| 151 | + |
| 152 | +## Operations and diagnostics |
| 153 | + |
| 154 | +### Health checks |
| 155 | + |
| 156 | +- `diffscope doctor` |
| 157 | +- `GET /api/status` |
| 158 | +- `GET /api/doctor` |
| 159 | +- `GET /metrics` |
| 160 | +- Helm `test-connection` |
| 161 | + |
| 162 | +### Failure forensics bundles |
| 163 | + |
| 164 | +DiffScope now writes JSON forensics bundles for degraded review and eval runs. |
| 165 | + |
| 166 | +- Review bundles: `~/.local/share/diffscope/forensics/reviews/<review-id>/` |
| 167 | +- Eval bundles: `~/.local/share/diffscope/forensics/eval/...` or `<artifact-dir>/forensics/...` |
| 168 | + |
| 169 | +Review manifests are available from the protected endpoint: |
| 170 | + |
| 171 | +```text |
| 172 | +GET /api/review/{id}/forensics |
| 173 | +``` |
| 174 | + |
| 175 | +### Production replay evals |
| 176 | + |
| 177 | +Accepted and rejected review outcomes are captured into an anonymized replay pack at: |
| 178 | + |
| 179 | +```text |
| 180 | +~/.local/share/diffscope/eval/production_replay/replay.json |
| 181 | +``` |
| 182 | + |
| 183 | +Run it with the normal eval command: |
| 184 | + |
| 185 | +```bash |
| 186 | +diffscope eval --fixtures ~/.local/share/diffscope/eval/production_replay |
| 187 | +``` |
0 commit comments