sphinx-understand 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.sphinxconfig.example +10 -0
- package/.sphinxignore.example +22 -0
- package/CONTRIBUTING.md +19 -0
- package/LICENSE +21 -0
- package/README.md +186 -2
- package/bin/sphinx.js +9 -0
- package/docs/architecture.md +212 -0
- package/docs/configuration.md +241 -0
- package/docs/integrations.md +135 -0
- package/docs/logo.svg +3 -0
- package/eval/README.md +38 -0
- package/eval/RESULTS.md +205 -0
- package/eval/fixtures/known-false-negatives.json +115 -0
- package/examples/browser-demo.mjs +28 -0
- package/examples/config.json +59 -0
- package/package.json +50 -4
- package/src/activation-worker.js +10 -0
- package/src/activation.js +187 -0
- package/src/agent-settings.js +206 -0
- package/src/agent.js +45 -0
- package/src/browser-interview.js +344 -0
- package/src/browser-page.js +427 -0
- package/src/change-view.js +314 -0
- package/src/check-recovery.js +92 -0
- package/src/checkbox.js +148 -0
- package/src/cli.js +563 -0
- package/src/config.js +248 -0
- package/src/cursor-hook.js +18 -0
- package/src/evaluator.js +501 -0
- package/src/git-gate.js +116 -0
- package/src/git-interview.js +51 -0
- package/src/git.js +252 -0
- package/src/help.js +122 -0
- package/src/ignore.js +94 -0
- package/src/install.js +448 -0
- package/src/lifecycle-integrations.js +259 -0
- package/src/logo.js +6 -0
- package/src/mcp.js +352 -0
- package/src/model-presets.js +79 -0
- package/src/native-check.js +166 -0
- package/src/openrouter.js +269 -0
- package/src/overrides.js +68 -0
- package/src/pi-integration.js +179 -0
- package/src/pi-runtime.js +128 -0
- package/src/preparation.js +254 -0
- package/src/presentations.js +74 -0
- package/src/prompts.js +181 -0
- package/src/repo-config.js +72 -0
- package/src/repo-context.js +43 -0
- package/src/review-workspace.js +334 -0
- package/src/reviewer-limits.js +10 -0
- package/src/reviewer-response.js +22 -0
- package/src/reviewer.js +527 -0
- package/src/routing.js +40 -0
- package/src/sessions.js +377 -0
- package/src/stream.js +59 -0
- package/src/terminal-launch.js +288 -0
- package/src/terminal-worker.js +11 -0
- package/src/terminal.js +121 -0
- package/src/usage.js +31 -0
- package/src/version.js +4 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Configuration, models, and cost
|
|
2
|
+
|
|
3
|
+
This page is the reference for reviewer models, usage limits, repository policy, and file exclusions. For the first-run path, see the [README](../README.md).
|
|
4
|
+
|
|
5
|
+
- [Settings locations](#settings-locations)
|
|
6
|
+
- [Reviewer models](#reviewer-models)
|
|
7
|
+
- [Routing and question counts](#routing-and-question-counts)
|
|
8
|
+
- [Model calls, tokens, and limits](#model-calls-tokens-and-limits)
|
|
9
|
+
- [Repository policy](#repository-policy)
|
|
10
|
+
- [Project context](#project-context)
|
|
11
|
+
- [Files Sphinx never reads](#files-sphinx-never-reads)
|
|
12
|
+
- [Background preparation](#background-preparation)
|
|
13
|
+
|
|
14
|
+
## Settings locations
|
|
15
|
+
|
|
16
|
+
| What | Where |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Machine-wide settings | `~/.config/sphinx/config.json` |
|
|
19
|
+
| OpenRouter key and OpenAI-compatible endpoint | `~/.config/sphinx/credentials.json` (mode `0600`) |
|
|
20
|
+
| Machine-wide ignore patterns | `~/.config/sphinx/ignore` |
|
|
21
|
+
| Skip and yolo log | `~/.config/sphinx/overrides.jsonl` |
|
|
22
|
+
| Repository policy | `.sphinxconfig` (legacy `.sphinx.json` is read when `.sphinxconfig` is absent) |
|
|
23
|
+
| Repository exclusions | `.sphinxignore` |
|
|
24
|
+
| Project context | `.sphinxcontext.md` |
|
|
25
|
+
|
|
26
|
+
`SPHINX_HOME` relocates all machine-wide settings, credentials, and assessment state. `sphinx config` shows effective settings and paths. A complete global example using the paid Haiku preset is in [examples/config.json](../examples/config.json).
|
|
27
|
+
|
|
28
|
+
Model routes, credentials, and usage limits are machine-wide only. A repository cannot redirect review to another provider, supply credentials, or raise your limits.
|
|
29
|
+
|
|
30
|
+
## Reviewer models
|
|
31
|
+
|
|
32
|
+
Sphinx picks one of three saved routes (small, medium, large) for each change. Presets fill all three; you can change them at any time without reinstalling:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
sphinx config --preset claude-economy
|
|
36
|
+
sphinx config --preset openrouter-value --allow-paid
|
|
37
|
+
sphinx config --small claude:haiku --medium claude:haiku --large claude:sonnet
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Preset | Small and medium | Large | Usage source |
|
|
41
|
+
| --- | --- | --- | --- |
|
|
42
|
+
| `codex-economy` | `codex:gpt-6-luna` | `codex:gpt-6-luna` | Your Codex CLI account |
|
|
43
|
+
| `claude-economy` | `claude:haiku` | `claude:haiku` | Your Claude CLI account |
|
|
44
|
+
| `openrouter-value` (experimental) | `openrouter:anthropic/claude-haiku-5.5` | `openrouter:anthropic/claude-haiku-5.5` | Paid OpenRouter credits |
|
|
45
|
+
| `openrouter-deepseek` (experimental) | `openrouter:deepseek/deepseek-v3.2` | `openrouter:deepseek/deepseek-v3.2` | Paid OpenRouter credits |
|
|
46
|
+
| `openrouter-free` | `openrouter:openrouter/free` | `openrouter:openrouter/free` | OpenRouter free availability and limits |
|
|
47
|
+
|
|
48
|
+
Unattended installation needs an explicit preset or route; Sphinx does not silently choose a free model:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
sphinx install --yes --preset codex-economy
|
|
52
|
+
sphinx install --yes --preset claude-economy
|
|
53
|
+
sphinx install --yes --preset openrouter-value --allow-paid
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Reinstalling keeps saved routes unless you choose a replacement. Updating Sphinx does not migrate saved routes. Changing a route invalidates prepared questions and completion records made under the previous route.
|
|
57
|
+
|
|
58
|
+
### Codex and Claude routes
|
|
59
|
+
|
|
60
|
+
These use your signed-in Codex or Claude CLI and consume that account's allowance. You need a recent CLI with access to the selected model; see [Codex models](https://learn.chatgpt.com/docs/models) and [Claude model configuration](https://code.claude.com/docs/en/model-config). The economy presets keep the same economical model for all tiers; investigation effort and question count still scale with change size. The Claude `haiku` alias follows the available Haiku model. Neither preset upgrades to a more expensive model.
|
|
61
|
+
|
|
62
|
+
**These routes bill your signed-in plan by default.** Sphinx removes `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `CODEX_API_KEY`, and similar variables from the reviewer CLI's environment, so a key in your shell cannot silently switch reviews to API credits. If the CLI is not signed in with a Claude or ChatGPT plan, the check stops with instructions. To let the CLIs use API keys instead, run `sphinx config --cli-billing api`.
|
|
63
|
+
|
|
64
|
+
Each call is a fresh, isolated CLI invocation used as a model transport underneath the embedded [Pi SDK](https://pi.dev/docs/latest/sdk) reviewer. It does not reuse your coding conversation. See [architecture](architecture.md#independent-investigation-and-compaction).
|
|
65
|
+
|
|
66
|
+
Pi, Cursor, and OpenCode integrations present checkpoints but do not supply a reviewer model. Their users pick a Codex/Claude CLI route, OpenRouter, or an OpenAI-compatible endpoint.
|
|
67
|
+
|
|
68
|
+
### OpenRouter routes
|
|
69
|
+
|
|
70
|
+
**Every OpenRouter route requires an API key, including free models.** The installer accepts an existing `OPENROUTER_API_KEY` or prompts for one with hidden input; `sphinx auth` replaces it later. Create a key in [OpenRouter's key settings](https://openrouter.ai/settings/keys). The key is stored in a user-only local file, not an OS keychain, and never in project configuration.
|
|
71
|
+
|
|
72
|
+
Filtered evidence goes to OpenRouter and its selected upstream provider, billed separately from your coding-agent plan. Paid routes need OpenRouter credits.
|
|
73
|
+
|
|
74
|
+
- **Paid consent.** Guided setup labels paid choices. Noninteractive commands need `--allow-paid` or an existing `allowPaid: true` setting. Free routes send zero-price provider limits even when another route permits paid models. There are no automatic paid fallbacks.
|
|
75
|
+
- **Free router.** `openrouter-free` is best-effort. Its model selection, rate limits, and tool support can interrupt a check; see [OpenRouter limits](https://openrouter.ai/docs/api_reference/limits). Sphinx does not switch providers or upgrade models after a failure.
|
|
76
|
+
- **Endpoint compatibility.** Requests need endpoint support for tools and output parameters. Capability metadata is a compatibility check, not a guarantee; unusable output leaves the check pending. See OpenRouter [provider routing](https://openrouter.ai/docs/guides/routing/provider-selection) and [structured outputs](https://openrouter.ai/docs/guides/features/structured-outputs).
|
|
77
|
+
|
|
78
|
+
### OpenAI-compatible endpoints
|
|
79
|
+
|
|
80
|
+
Any OpenAI chat-completions-compatible endpoint (OpenAI, Groq, Together, vLLM, Ollama, LM Studio, and others) can run reviews. It must support tool calls and JSON-schema structured output.
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
sphinx auth --provider openai --base-url https://api.openai.com/v1 # prompts for the key (hidden)
|
|
84
|
+
sphinx config --provider openai --model gpt-5-mini # or per size: --large openai:<model>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The key is stored next to its URL and only ever sent there. Plain `http://` is allowed only for localhost, where a key is optional. For scripts, set `SPHINX_OPENAI_BASE_URL`, plus `SPHINX_OPENAI_API_KEY` unless the endpoint is localhost. Sphinx never reads `OPENAI_API_KEY`.
|
|
88
|
+
|
|
89
|
+
### Reference pricing and quality
|
|
90
|
+
|
|
91
|
+
The paid value preset uses Haiku 5.5 with an 8,192-token output ceiling, including reasoning. Reference prices checked **October 15, 2026** start at $0.10 input / $0.50 output per million tokens below 100,000 input tokens; the higher context tier is $0.50 / $2.50. Rates vary by endpoint and over time; see [Haiku endpoints](https://openrouter.ai/api/v1/models/anthropic/claude-haiku-5.5/endpoints). At the lower rates, 30,000 input plus 2,000 output tokens costs about $0.004. A whole check makes several requests with repeated context.
|
|
92
|
+
|
|
93
|
+
The [evaluation results](../eval/RESULTS.md) record measured question quality, grading failures, and corrections across Haiku, Qwen, DeepSeek, and GLM on synthetic changes. They are a limited development benchmark, not a reliability guarantee. The Haiku preset is experimental because it rejected a sufficient qualitative answer in a focused test; DeepSeek is an experimental open-weight preset. Price and tool support alone do not establish question quality.
|
|
94
|
+
|
|
95
|
+
## Routing and question counts
|
|
96
|
+
|
|
97
|
+
Routing is deterministic and makes no model request. It counts **added plus deleted lines**, changed files, and consequential path terms. Ignored files do not count.
|
|
98
|
+
|
|
99
|
+
| Tier | Default rule |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| Small | At most 80 changed lines and 3 files |
|
|
102
|
+
| Medium | Between the small and large thresholds |
|
|
103
|
+
| Large | At least 400 changed lines, 12 files, or a consequential path |
|
|
104
|
+
|
|
105
|
+
Consequential paths contain `auth`, `permission`, `migration`, `billing`, `payment`, `crypto`, `security`, or `terraform`. A matching path makes even a tiny patch large. These are configurable heuristics, not a semantic risk classification.
|
|
106
|
+
|
|
107
|
+
The tier and your chosen depth set the maximum number of initial questions:
|
|
108
|
+
|
|
109
|
+
| Change tier | Relaxed | Standard | Thorough |
|
|
110
|
+
| --- | --- | --- | --- |
|
|
111
|
+
| Small | 1 | 1 | 1 |
|
|
112
|
+
| Medium | Up to 2 | Up to 2 | Up to 3 |
|
|
113
|
+
| Large | Up to 2 | Up to 3 | Up to 5 |
|
|
114
|
+
|
|
115
|
+
- `relaxed`: observable behavior and the most consequential edge case.
|
|
116
|
+
- `standard`: behavior, failure modes, and relevant system interactions.
|
|
117
|
+
- `thorough`: also supported rollout, rollback, and compatibility assumptions.
|
|
118
|
+
|
|
119
|
+
These are ceilings, not quotas: the reviewer asks fewer questions when the evidence supports fewer distinct behaviors, and never pads. A wrong answer adds a replacement question for the same concept, so a check can ask more than the initial count. Changing the model does not change the question count.
|
|
120
|
+
|
|
121
|
+
## Model calls, tokens, and limits
|
|
122
|
+
|
|
123
|
+
**Model calls have no default cap** (`maxModelCalls: null`, `agentMaxTurns: null`). Every request is counted: background investigation, compaction, the question audit, grading, replacement audits, and failed requests. The questionnaire shows calls and tokens as the check runs, plus cost when the provider reports it.
|
|
124
|
+
|
|
125
|
+
| Step | Typical requests |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| Investigation for a small / medium / large change | Aims for 5 / 7 / 8, including the question audit. These are planning targets, not stops. |
|
|
128
|
+
| Each answer, learning request, or dispute | 1 |
|
|
129
|
+
| A proposed replacement question | 1 more, for an independent source audit |
|
|
130
|
+
| Status, help, config, pending, or pushing an already approved change | 0 |
|
|
131
|
+
|
|
132
|
+
Set or clear an optional cap. This changes no routes and makes no model request:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
sphinx config --max-model-calls 30 # 1–100
|
|
136
|
+
sphinx config --max-model-calls unlimited # `none` is an alias
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- Existing numeric caps stay in effect until changed. A check adopts an edited cap when resumed, preserving questions, progress, and counted calls. Lowering a cap below current usage blocks further calls.
|
|
140
|
+
- An explicit cap reserves calls for grading and the final audit; a lone remaining request cannot start a question synthesis that would lack its audit.
|
|
141
|
+
- `agentMaxTurns` (advanced) caps investigation, compaction, question generation, and auditing for one review attempt.
|
|
142
|
+
|
|
143
|
+
Other limits always apply:
|
|
144
|
+
|
|
145
|
+
| Setting | Default | Bounds |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `timeoutSeconds` | 180 | The whole investigation. Unlimited calls do not mean unlimited time. |
|
|
148
|
+
| `maxContextBytes` | 100,000 | Serialized review context (prompts, tools, schemas), not the whole diff. Pi compacts before this; context that still does not fit is rejected before a model call. |
|
|
149
|
+
| `toolResultBytes` | 16,000 | Each tool page. Pages shrink to leave room for batched reads. |
|
|
150
|
+
| `maxOutputTokens` | 4,096 (8,192 in `openrouter-value`) | Every request, 512–16,384. Set with `sphinx config --max-output-tokens 8192`. |
|
|
151
|
+
|
|
152
|
+
OpenRouter counts hidden reasoning within `maxOutputTokens`; a higher ceiling can prevent truncation and permits more billed output. Codex and Claude CLIs get concise-output instructions and local timeout and output-byte limits, but their interfaces have no equivalent hard token cap. Small and medium changes request low reasoning effort; large changes request medium effort where the CLI supports it.
|
|
153
|
+
|
|
154
|
+
**Retries.** Provider failures never retry automatically and never switch providers. Cache warming is disabled. Without a call cap, the reviewer stops after three consecutive invalid responses. Correctable tool or question-validation errors are returned to Pi as feedback within any explicit cap. If a review fails, the questionnaire offers to continue from saved work; Pause is the default. From a terminal, `sphinx check --id <id>` resumes saved work, and `--retry-review` gives a failed, questionless review one further attempt (with an explicit cap, up to `maxModelCalls` additional requests). Setup, credential, stale-code, and evidence-loading failures must be fixed first.
|
|
155
|
+
|
|
156
|
+
Call caps bound requests and byte limits bound evidence. Neither is a dollar or subscription ceiling. **Set provider-side spending limits for paid accounts.**
|
|
157
|
+
|
|
158
|
+
## Repository policy
|
|
159
|
+
|
|
160
|
+
`sphinx init` creates `.sphinxconfig`, `.sphinxignore`, and `.sphinxcontext.md` when they are absent and never overwrites them. Edit the files directly afterwards. Commit them to share policy with collaborators. Start from `sphinx init` or [.sphinxconfig.example](../.sphinxconfig.example):
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"version": 1,
|
|
165
|
+
"events": ["pre-push"],
|
|
166
|
+
"branches": ["main", "release/*"],
|
|
167
|
+
"level": "standard",
|
|
168
|
+
"exclude": ["vendor/**"]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
| Key | Meaning |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `enabled` | `false` disables Sphinx for this repository |
|
|
175
|
+
| `events` | `pre-push`, `pre-commit`, or both |
|
|
176
|
+
| `branches` | Push policies match the **destination** branch; commit policies match the current local branch |
|
|
177
|
+
| `remotes` | Remote name patterns for pushes; default `*` |
|
|
178
|
+
| `level` | `relaxed`, `standard`, or `thorough` |
|
|
179
|
+
| `exclude` | Extra ignore patterns, added to machine-wide ones |
|
|
180
|
+
| `backgroundPreparation` | `false` opts this repository out |
|
|
181
|
+
|
|
182
|
+
Branch defaults come from machine-wide settings (initially `main` and `master`), not from the branch you happen to have checked out. Without prompts:
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
sphinx init --yes --branches main --events pre-push --level standard
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
If both `.sphinxconfig` and legacy `.sphinx.json` exist, `.sphinxconfig` wins and they are not merged; `init` copies a legacy policy into `.sphinxconfig` and leaves the original.
|
|
189
|
+
|
|
190
|
+
**Commit checkpoints.** Enable `pre-commit`. To run one by hand, `sphinx check --staged` assesses the index, including partial staging.
|
|
191
|
+
|
|
192
|
+
**Manual push checks.** `sphinx check --remote origin --branch main` selects the destination; otherwise Sphinx uses the upstream. Multiple destination refs are assessed separately. Tag-only pushes and deletions do not trigger checks in v0.1.
|
|
193
|
+
|
|
194
|
+
## Project context
|
|
195
|
+
|
|
196
|
+
`.sphinxcontext.md` describes what the project does, who uses it, important workflows, and architecture boundaries. It is included in every reviewer, compaction, and grading request.
|
|
197
|
+
|
|
198
|
+
```sh
|
|
199
|
+
sphinx init --yes --context 'A booking service for shared equipment. Reservations must never overlap.'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- Keep it under 16,000 bytes and free of secrets. It respects `.sphinxignore`.
|
|
203
|
+
- The reviewer checks its claims against code. It cannot override Sphinx policy or authorize reading ignored files.
|
|
204
|
+
- Without context, the reviewer establishes purpose from documentation and source rather than inventing requirements.
|
|
205
|
+
- Changing it invalidates prepared questions and completion records.
|
|
206
|
+
|
|
207
|
+
## Files Sphinx never reads
|
|
208
|
+
|
|
209
|
+
Built-in exclusions apply recursively and cannot be undone by project negations:
|
|
210
|
+
|
|
211
|
+
- `.env` and `.env.*`, including `.env.example`.
|
|
212
|
+
- Private key and keystore names: `*.pem`, `*.key`, `*.p12`, `*.pfx`, `*.jks`, `*.keystore`, `id_rsa`, `id_ed25519`, and related SSH names.
|
|
213
|
+
- Credential files: `.netrc`, `.npmrc`, `.pypirc`, `*credentials*.json`, `service-account*.json`, `secrets.json`, `secrets.yaml`, `secrets.yml`.
|
|
214
|
+
|
|
215
|
+
Add project exclusions to `.sphinxignore`:
|
|
216
|
+
|
|
217
|
+
```gitignore
|
|
218
|
+
# Project-specific private or generated files
|
|
219
|
+
internal/customer-exports/
|
|
220
|
+
/config/production.json
|
|
221
|
+
*.generated.ts
|
|
222
|
+
dist/
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Supported syntax is `*`, `**`, `?`, root `/`, directory suffix `/`, `#` comments, and local `!` negations; escape a leading `#` or `!` with `\`. This is a small gitignore-like parser, not the full Git pattern language. Project rules cannot undo machine-wide (`~/.config/sphinx/ignore`) or built-in exclusions. Ignore-policy symlinks are rejected. `.gitignore` is not applied to tracked files.
|
|
226
|
+
|
|
227
|
+
**Filtering happens before patch, line-count, and content retrieval, including searches of unchanged files.** Ignored files' contents are not read, saved as evidence, or sent to a model. Git may list their names and object IDs locally to identify changes. A change that touches only ignored files needs no assessment.
|
|
228
|
+
|
|
229
|
+
Ignore rules match paths. They do not detect a secret inside an included source file. Add sensitive paths before your first assessment.
|
|
230
|
+
|
|
231
|
+
Evidence comes from Git objects, not your working files: pre-commit reads the staged index, pre-push reads commits. `.sphinxcontext.md` is read from the working directory and its hash is bound to the assessment. Snapshot identity covers the full commit or index, so editing an ignored file alongside an assessed change can still invalidate the earlier completion.
|
|
232
|
+
|
|
233
|
+
## Background preparation
|
|
234
|
+
|
|
235
|
+
After commits, merges, rewrites, and checkouts, Sphinx schedules a detached reviewer for the expected destination so questions are ready before you push. It uses local remote-tracking refs and never fetches. It never opens a questionnaire or approves a push.
|
|
236
|
+
|
|
237
|
+
- `sphinx status` shows preparation progress; `sphinx prepare` schedules it explicitly; `sphinx prepare --retry` retries a failed job (failures never retry on their own).
|
|
238
|
+
- Preparation and the push check share one assessment, lock, question set, and usage count. A change to source, destination, policy, ignore rules, or context discards prepared work.
|
|
239
|
+
- Set `backgroundPreparation: false` in `config.json` or `.sphinxconfig` to opt out. A repository cannot re-enable preparation disabled machine-wide.
|
|
240
|
+
- While yolo is on, preparation is paused: no new model request starts, although one already in progress may finish.
|
|
241
|
+
- A first push, a branch without local tracking history, or a push to an unexpected destination needs a cold review at push time. Pre-commit checks always review on demand. Run `git fetch` if remote history is missing.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Integrations and troubleshooting
|
|
2
|
+
|
|
3
|
+
The Git hook is the checkpoint. It works on its own, including for pushes from a terminal or GUI client. Coding-agent integrations add two things: guidance telling the agent to wait for a blocked Git command, and fallback forms for checks that could not open in the browser. For the first-run path, see the [README](../README.md).
|
|
4
|
+
|
|
5
|
+
- [Supported clients](#supported-clients)
|
|
6
|
+
- [Choosing and opening clients](#choosing-and-opening-clients)
|
|
7
|
+
- [Per-client notes](#per-client-notes)
|
|
8
|
+
- [How a checkpoint reaches you](#how-a-checkpoint-reaches-you)
|
|
9
|
+
- [Remote machines, SSH, and CI](#remote-machines-ssh-and-ci)
|
|
10
|
+
- [Git hooks and existing hooks](#git-hooks-and-existing-hooks)
|
|
11
|
+
- [Manual JSON protocol](#manual-json-protocol)
|
|
12
|
+
- [Troubleshooting](#troubleshooting)
|
|
13
|
+
- [Uninstall](#uninstall)
|
|
14
|
+
|
|
15
|
+
## Supported clients
|
|
16
|
+
|
|
17
|
+
| Client | Checkpoint | Fallback | Installed integration |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| Codex | Local browser questionnaire | Native MCP form | MCP server and lifecycle hooks |
|
|
20
|
+
| Claude Code | Local browser questionnaire | Native MCP form | MCP server and lifecycle hooks |
|
|
21
|
+
| Pi 1.2+ | Local browser questionnaire | Native dialogs | Local Pi extension |
|
|
22
|
+
| Cursor 1.7+ | Local browser questionnaire | Browser, after Git exits | Local user hooks |
|
|
23
|
+
| OpenCode 1.x | Local browser questionnaire | Browser, after Git exits | Local OpenCode plugin |
|
|
24
|
+
|
|
25
|
+
Client integrations are separate from the reviewer model. Pi, Cursor, and OpenCode do not supply reviewer authentication; choose a Codex/Claude CLI route, OpenRouter, or an OpenAI-compatible endpoint (see [configuration](configuration.md#reviewer-models)).
|
|
26
|
+
|
|
27
|
+
## Choosing and opening clients
|
|
28
|
+
|
|
29
|
+
`--agents auto` (the default) detects clients by executable, configuration directory, or an existing Sphinx installation. Guided setup shows checkboxes with **All supported agents** first and detected clients preselected: arrow keys move, Space toggles, Enter confirms. Clear every box to skip agent setup; previously connected integrations stay installed.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
sphinx install --agents codex,claude,pi,cursor,opencode # explicit subset
|
|
33
|
+
sphinx install --agents none # Git only
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run `sphinx install` again after installing a new supported client; Sphinx does not discover new clients on its own.
|
|
37
|
+
|
|
38
|
+
Interactive installation opens the selected clients afterwards: fresh Codex, Claude Code, Pi, and OpenCode CLI sessions, or a new Cursor window. Opening a client sends no prompt and makes no Sphinx model request. Existing client processes are not restarted.
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
sphinx install --no-launch # install without opening clients
|
|
42
|
+
sphinx install --yes --preset codex-economy --launch # unattended install, then open
|
|
43
|
+
sphinx activate # open configured clients later
|
|
44
|
+
sphinx activate --agents codex,claude
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`activate` does not reinstall or change settings; `--json` returns launch results. If a client is missing or no terminal or editor can be opened, Sphinx prints the command to run yourself.
|
|
48
|
+
|
|
49
|
+
Opening a client does not verify MCP connectivity or hook trust. Sphinx never bypasses a client's trust review. Check what Sphinx can see with `sphinx doctor`.
|
|
50
|
+
|
|
51
|
+
## Per-client notes
|
|
52
|
+
|
|
53
|
+
**Codex.** Open `/hooks` and trust the Sphinx hooks; `sphinx doctor` cannot verify this. Codex approval policies can cancel native forms: in Codex 0.162.1, approval policy `never` cancels them unless the host enables full-access form input for the user thread. A cancelled form leaves the check pending; finish it with `sphinx check` in a terminal. Sphinx does not change your approval policy.
|
|
54
|
+
|
|
55
|
+
**Claude Code.** Start a new session to load the hooks. Confirm the `sphinx` server is connected in `/mcp`.
|
|
56
|
+
|
|
57
|
+
**Pi.** Start a new session, or run `/reload` in an existing one. Native fallback dialogs need an interactive session or a dialog-capable RPC client; noninteractive modes leave the check pending for `sphinx check`.
|
|
58
|
+
|
|
59
|
+
**Cursor.** Start a new Agent conversation in the opened window. Activation flags versions older than 1.7 for an update. The installed user hooks cover local sessions, not Cursor cloud agents.
|
|
60
|
+
|
|
61
|
+
**OpenCode.** Start a new session. The plugin is installed in OpenCode's configuration directory (honoring `OPENCODE_CONFIG_DIR` or `XDG_CONFIG_HOME`).
|
|
62
|
+
|
|
63
|
+
Each client controls how its own forms and dialogs look, and may keep its own interaction logs.
|
|
64
|
+
|
|
65
|
+
## How a checkpoint reaches you
|
|
66
|
+
|
|
67
|
+
1. **Browser (normal).** The blocked Git hook serves a questionnaire on `127.0.0.1` and prints its URL. On macOS it opens in a background browser tab without activating Terminal or moving your coding window; elsewhere, open the printed URL. One page handles every checkpoint in a Git operation. Git continues when you pass.
|
|
68
|
+
2. **Native fallback.** If the browser page cannot be presented, Git stops and the check is queued. Codex and Claude Code show an MCP form after the shell command exits; Pi shows extension dialogs; Cursor and OpenCode point you to the browser page. Because Git has already exited, passing a fallback check does not resume it; run the Git command again once.
|
|
69
|
+
3. **Terminal.** `sphinx check` runs the same check in your terminal at any time. It supports `/learn`, `/dispute <reason>`, and `/quit` (save and leave pending).
|
|
70
|
+
|
|
71
|
+
All three share one assessment per change. **Your answers go directly to Sphinx; the coding model never sees questions, answers, or feedback.** It receives only status, assessment IDs, progress, and usage counts. It does not start the interview or relay answers, and there is no extra coding-model turn per answer. A paused or dismissed check does not reopen on unrelated shell commands; retrying the blocked Git command queues it again. The integration follows checks across `cd` and `git -C`.
|
|
72
|
+
|
|
73
|
+
Agent guidance tells the coding agent not to start a duplicate Git command while one is waiting and not to answer for you. The host may still cancel a long-running shell command before you finish; in that case, complete the check and retry once.
|
|
74
|
+
|
|
75
|
+
## Remote machines, SSH, and CI
|
|
76
|
+
|
|
77
|
+
The installation covers your local machine. Remote machines, containers, and hosted coding agents need their own installation.
|
|
78
|
+
|
|
79
|
+
Sphinx opens the browser automatically only on macOS. On Linux, WSL, and over SSH it prints the loopback URL instead. From a remote session, forward the same port number (for example `ssh -L <port>:127.0.0.1:<port> host`) and open the printed URL unchanged in your local browser; the page rejects other hosts and ports. Or run `sphinx check` on the remote machine. A remote connection may time out sooner than Sphinx's 25-minute wait.
|
|
80
|
+
|
|
81
|
+
CI never starts a questionnaire. The check stays pending and Git stops.
|
|
82
|
+
|
|
83
|
+
## Git hooks and existing hooks
|
|
84
|
+
|
|
85
|
+
`sphinx install` sets a machine-wide Git `core.hooksPath`, which covers existing and new repositories that use that Git configuration. Existing repository hooks still run first, with their arguments and input, and their rejection is preserved. Hooks with streaming protocols are forwarded directly. Reinstallation is idempotent, and agent settings are merged rather than replaced.
|
|
86
|
+
|
|
87
|
+
A repository that sets its own `core.hooksPath` needs a compatibility step. `sphinx doctor` reports this:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
cd your-repo
|
|
91
|
+
sphinx install --repo
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Besides the checkpoint hooks, `post-commit`, `post-merge`, `post-rewrite`, and `post-checkout` schedule [background preparation](configuration.md#background-preparation).
|
|
95
|
+
|
|
96
|
+
## Manual JSON protocol
|
|
97
|
+
|
|
98
|
+
For integrations and debugging, the CLI returns questions and feedback as JSON. It never returns answer keys. Codex and Claude use `sphinx mcp` internally, and Pi calls the same controller from its extension; none of them asks the coding model to run these commands.
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
sphinx pending --json
|
|
102
|
+
sphinx check --json
|
|
103
|
+
sphinx answer <assessment-id> --text 'Your answer and reason' --json
|
|
104
|
+
sphinx explain <assessment-id> --json
|
|
105
|
+
sphinx dispute <assessment-id> --text 'Why the premise is wrong' --json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
These are for a person or a test harness. A coding agent must not answer on your behalf.
|
|
109
|
+
|
|
110
|
+
`help`, `status`, `pending`, and `config` never call a model. `--json` output contains no banners or ANSI styling; color is off when output is redirected, and `NO_COLOR=1` disables it.
|
|
111
|
+
|
|
112
|
+
## Troubleshooting
|
|
113
|
+
|
|
114
|
+
| Symptom | What to do |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| Git is waiting and no page opened | Open the `Sphinx questionnaire:` URL that Git printed. |
|
|
117
|
+
| You closed the tab | Git keeps waiting. Reopen the same URL until the 25-minute deadline. |
|
|
118
|
+
| You paused, the deadline passed, or the host cancelled the shell | Progress is saved. Run the Git command once more, or `sphinx check` first. |
|
|
119
|
+
| A native form was cancelled or never appeared | Run `sphinx check` in a terminal. In Codex, see the approval policy note above. |
|
|
120
|
+
| The review failed before questions appeared | The page offers to continue from saved work. From a terminal: `sphinx check --id <id>`, or `--retry-review` for a failed, questionless review. See [limits](configuration.md#model-calls-tokens-and-limits). |
|
|
121
|
+
| The check keeps coming back after you passed | Something changed: code, destination base, policy, ignore rules, context, or reviewer route. Completion also expires after 24 hours. |
|
|
122
|
+
| Hooks do not run in one repository | `sphinx doctor`, then `sphinx install --repo` if it reports a hooks override. |
|
|
123
|
+
| Missing remote history | `git fetch`, then push again. |
|
|
124
|
+
|
|
125
|
+
Never start a second copy of a Git command that is still waiting.
|
|
126
|
+
|
|
127
|
+
## Uninstall
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
sphinx uninstall --repo # remove an explicit repository integration, if present
|
|
131
|
+
sphinx uninstall # remove machine-wide Git and agent integrations
|
|
132
|
+
npm uninstall -g sphinx-understand
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Uninstall restores the previous hook configuration when Sphinx still owns it and removes only its own unchanged agent handlers and MCP registration. Later edits are preserved and reported. Machine-wide uninstall leaves explicit repository installations in place, with a warning; remove those first. Configuration, credentials, and assessment state stay in `~/.config/sphinx` for you to keep or delete.
|
package/docs/logo.svg
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" fill="#16130f">
|
|
2
|
+
<style>@media (prefers-color-scheme: dark){svg{fill:#ede7dd}}</style><mask id="m"><rect width="64" height="64" fill="#fff"/><path d="M24 22h16v14c0 6-3.6 10-8 10s-8-4-8-10z" fill="#000"/><rect x="26.5" y="44" width="11" height="12" fill="#000"/><rect x="17" y="18.2" width="30" height="1.8" fill="#000"/><g fill="#000"><rect y="26" width="21" height="2.2"/><rect x="43" y="26" width="21" height="2.2"/><rect y="32" width="21" height="2.2"/><rect x="43" y="32" width="21" height="2.2"/><rect y="38" width="21" height="2.2"/><rect x="43" y="38" width="21" height="2.2"/><rect y="44" width="21" height="2.2"/><rect x="43" y="44" width="21" height="2.2"/><rect y="50" width="21" height="2.2"/><rect x="43" y="50" width="21" height="2.2"/></g></mask>
|
|
3
|
+
<path mask="url(#m)" d="M24 5h16c5 0 8.5 3.5 10 9l6 16-4 2v28H12V32l-4-2 6-16c1.5-5.5 5-9 10-9z"/><rect x="26.6" y="27.4" width="4.2" height="2.2" rx="1.1"/><rect x="33.2" y="27.4" width="4.2" height="2.2" rx="1.1"/><rect x="29.2" y="38.6" width="5.6" height="1.8" rx=".9"/><path d="M29.4 47.2h5.2l-.6 9.4h-4z"/></svg>
|
package/eval/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Reviewer evaluation
|
|
2
|
+
|
|
3
|
+
The [measured results](RESULTS.md) record the synthetic live runs, failed comparisons, manual quality findings and reported costs.
|
|
4
|
+
|
|
5
|
+
Run the deterministic baseline:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm run eval -- --out /tmp/sphinx-eval-baseline.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
It creates five temporary, committed Git repositories, verifies their curated facts, and runs Sphinx's real Pi reviewer, immutable workspace, evidence validation and grading pipeline with scripted model responses. It also runs existing missing-evidence, native compaction and explicit recovery regressions. This tests the harness and fixtures; it does not measure model quality. Temporary repositories and their isolated Sphinx homes are removed afterward. No real pending checkpoint or receipt is read or created.
|
|
12
|
+
|
|
13
|
+
`npm test` and `npm run check` preload a test-only network guard into Node and its spawned children. It rejects outbound fetch/HTTP/socket connections while permitting loopback and local IPC fixtures, preventing a partial model mock from silently reaching a real provider. Explicit live evaluations use the separate `npm run eval -- --live` entry point. The guard is not an OS sandbox for arbitrary non-Node executables.
|
|
14
|
+
|
|
15
|
+
The cases cover scoped card styling versus unchanged toolbar controls, process-local retry deduplication including a failure-handling bug, tenant authorization, environment override precedence, and retry behavior across twelve changed handlers. Each includes committed secret files excluded by built-in rules and `.sphinxignore`, plus dirty working-tree content. Distinct canaries and excluded paths are checked in memory against every outbound model payload and retained evidence.
|
|
16
|
+
|
|
17
|
+
Run a bounded live probe:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm run eval -- --live --case cosmetic --model openrouter/free \
|
|
21
|
+
--max-calls 20 --max-cost 0.10 --out /tmp/sphinx-eval-cosmetic.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Without `--model`, live mode uses the configured global OpenRouter tier routes. Paid routes require `--allow-paid` for this invocation, even if the product config permits them. The saved OpenRouter key or `OPENROUTER_API_KEY` is passed only in memory into the isolated fixture environment. Credentials and raw HTTP headers are never saved in reports. Use `--case retry,auth` to select cases, or `--probes generated` to focus on generated-question grading while iterating. Live requests pause for 1 second after a response by default; `--delay-ms` adjusts that interval. The first provider/authentication/transport failure stops the run and identifies probes that were not attempted. Failure telemetry includes the provider name, error type, a bounded credential-redacted message, and a valid numeric/date `Retry-After` value when returned.
|
|
25
|
+
|
|
26
|
+
The run-wide request limit covers generation, Pi compaction, grading and failed requests; there are no automatic retries or route changes. `--max-cost` uses provider-reported USD cost, including failed responses when reported. A completed request can exceed the threshold; the next request is blocked. Missing cost telemetry also blocks the next request when this option is set. This is a stop condition, not a guaranteed billing cap.
|
|
27
|
+
|
|
28
|
+
`--max-output-tokens 8192` can raise the per-request output allowance for a reasoning-heavy model in this evaluation only (allowed range: 512–16384). The report records this limit, including the model's reasoning allowance; it does not change saved product configuration. Transfer questions receive the production independent source audit too, and that extra request counts toward the same run-wide budget.
|
|
29
|
+
|
|
30
|
+
Artifacts include generated questions and private rubrics **for synthetic fixtures only**, exact retained evidence, curated answer probes, model verdicts, transfer questions, request counts, workspace reads, compactions, token counts and reported cost. They also retain the latest in-memory reviewer checkpoint and last proposed assessment, including after rejection, plus live audit and grading prompt/result/error transcripts, including rejected structured responses. Environment/config objects, raw HTTP headers, and opaque thinking fields are excluded; the supplied key is redacted from every report string. Generated questions are tested with independently authored source-grounded answers and misconceptions. For recognized explicit numeric `BATCH_SIZE` assignments, probes adapt to the visible question using the fixture's executable precedence rule; they never read the model's answer key. Recognized forms now include `BATCH_SIZE=5` and “BATCH_SIZE is set to 5”; detected unsupported assignments are marked uncovered. The latter form was added after the frozen V20 failure, without another live run. Inspect the probe's input scenario before classifying a mismatch; natural-language coverage is not universal. Canonical questions additionally test unsupported premises, a contradictory answer key, and disputes. Both invalid-key probes require ambiguity rather than awarding completion for correcting an invalid question. The retry case checks that identifying the actual failure-handling bug counts as understanding. Generation includes the production fresh question audit, charged within the same run-wide limit.
|
|
31
|
+
|
|
32
|
+
Concept coverage checks inspect the visible question, not private rubric text. Literal recall and missing causal/boundary prompts are flagged. These checks are explicit heuristics, not another model's opinion. Inspect flagged questions and rubrics before deciding whether a mismatch is a product bug or an incomplete fixture oracle. A passing fixture run is not a claim that arbitrary reviews are correct. The output report is refreshed after each case so a long run can be inspected before completion. For iteration, retain each report, change one behavior, rerun the same case and route, and compare the question, evidence, verdicts and total cost. `--json` prints the machine-readable report; a failed probe produces exit code 1, while `needs-review` is surfaced separately.
|
|
33
|
+
|
|
34
|
+
The CSS fixture checks selector/markup facts without a browser render. Its question tests propagation to an unchanged surface, not numeric CSS recall. Its oracle therefore does not claim to verify computed layout or visual appearance.
|
|
35
|
+
|
|
36
|
+
New questions carry private `acceptance.prediction` and `acceptance.causalReason` fields, separate from their fuller source-derived explanation. The curated fixtures author these minimum requirements independently, preserve the existing human answer probes, and still test contradictory full keys. Live reports retain the criteria so manual review can check both fairness and whether an essential asked behavior was omitted; matching a model's own criteria alone is not proof of a good assessment.
|
|
37
|
+
|
|
38
|
+
[Known false negatives](fixtures/known-false-negatives.json) preserve the exact V18 styling and V20 authorization questions, criteria, sufficient answers, observed ambiguous verdicts and synthetic source definitions. These are unresolved regressions, not passing tests. To replay one, select its `source.caseId` from `CASES`, overlay the saved `source.definition`, and call `createFixture(fixture, config)`. Read immutable evidence with `createReviewWorkspace(snapshot, config, { env })` and `canonicalEvidence(snapshot, record.source.requiredPaths, workspace)`, then build a review bound to that new `snapshot.id` and call `evaluator.gradeAnswer({ snapshot, question: record.question, answer: record.answer, review, config, env, beforeCall: budget.beforeCall })`. Use the existing metered evaluator transport and an explicit live budget; do not reuse an old temporary snapshot ID, re-audit to an easier question, or replace the saved human answer. This replay is not part of the default deterministic command.
|