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
package/eval/RESULTS.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Evaluation results — 2026-10-15
|
|
2
|
+
|
|
3
|
+
These are development measurements on five small, synthetic Git repositories, not a certification of arbitrary code reviews. The source changed between the earlier runs; the model comparisons are not a controlled benchmark. No real pending checkpoint, human answer, or receipt was used. Saved model routes and output limits were not changed by these evaluations.
|
|
4
|
+
|
|
5
|
+
The latest frozen-source coverage, V19/V20, generated seven questions across all five fixtures. Twelve of fourteen generated-question verdict probes matched; no canonical probes were rerun in this coverage. Fresh styling, retry and multifile checks passed independent source review. Authorization still rejected a sufficient explanation for not naming a specific code condition. Configuration exposed an uncovered fixture input phrasing and a malformed grade that validation rejected. The result is **not an all-green semantic evaluation**, despite all 560 guarded unit/integration tests passing.
|
|
6
|
+
|
|
7
|
+
Explicit minimum acceptance criteria improved the fresh styling question, but did not establish consistently fair grading. The failed legacy styling replays remain below, as do the current authorization failure and earlier model/provider failures. No tested route is established here as reliably correct for arbitrary repositories or answers.
|
|
8
|
+
|
|
9
|
+
## Reproduce
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm ci
|
|
13
|
+
npm run eval -- --out /tmp/sphinx-eval-scripted.json
|
|
14
|
+
npm run eval -- --live --case cosmetic --probes generated \
|
|
15
|
+
--model anthropic/claude-haiku-5.5 --allow-paid \
|
|
16
|
+
--max-calls 10 --max-cost 0.04 --max-output-tokens 8192 \
|
|
17
|
+
--delay-ms 1000 --skip-regressions --out /tmp/sphinx-eval-live-cosmetic.json
|
|
18
|
+
npm run eval -- --live --case retry,auth,config,multifile --probes generated \
|
|
19
|
+
--model anthropic/claude-haiku-5.5 --allow-paid \
|
|
20
|
+
--max-calls 35 --max-cost 0.15 --max-output-tokens 8192 \
|
|
21
|
+
--delay-ms 1000 --skip-regressions --out /tmp/sphinx-eval-live-remaining.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Live inference requires an existing OpenRouter key. Each invocation stops on a provider/transport failure; it does not automatically retry or change the selected model. The cost stop uses reported cost, may be exceeded by the final completed request, and blocks further requests if cost is missing. These are evaluation limits; they do not extend a product checkpoint's allowance.
|
|
25
|
+
|
|
26
|
+
The V11/V12 live measurements used the working tree based on `34bd7da9790b4110ec744256800ba1b847224303`, including uncommitted reviewer, evidence, audit, and eval changes. Pi was pinned to 1.2.0. The model-facing source loaded by V11 and V12 was the same. A separate presentation fix removed private concept labels from human questionnaires; a later transport diagnostic fix does not change model prompts. The transfer-distance fix described below was tested separately after V12 loaded its baseline. This commit alone therefore does not reproduce the worktree. The SHA-256 of the ordered path/content pairs for `src/evaluator.js`, `src/reviewer.js`, `src/pi-runtime.js`, `src/review-workspace.js`, `eval/cases.js`, `eval/harness.js`, and `eval/run.js` was `39bfce2b350afeb2f5d32bd42f6c9649e3bc9e2ad20e09e34aac7dbf33bcb39b` (UTF-8 path, NUL, file bytes, NUL for each).
|
|
27
|
+
|
|
28
|
+
## Deterministic baseline
|
|
29
|
+
|
|
30
|
+
`/tmp/sphinx-eval-scripted-final.json` passed all five fixtures and 35 verdict probes: 25 canonical probes plus 10 probes against generated questions. It made 59 scripted requests, including independent question and transfer audits. This exercises the real Pi/workspace/schema/grading pipeline with fake responses; it establishes harness behavior, not model quality. The related eval unit suite passed 14 tests. Seven selected regressions passed, covering omitted/invented evidence IDs, retained changed diffs, unread citations, native Pi compaction and explicit recovery. Earlier V11 artifacts ran only four of those regressions because a renamed evidence test no longer matched the runner's filter; the corrected final baseline retains the original artifacts.
|
|
31
|
+
|
|
32
|
+
The fixtures verify scoped CSS propagation, retry deduplication after failure, tenant isolation, environment/default precedence, and retry limits across twelve handlers. Executable source checks establish the non-CSS answers. CSS checks establish selector/markup relationships, not rendered layout. Tracked ignored files and dirty working-tree canaries were absent from every inspected outbound payload and retained evidence.
|
|
33
|
+
|
|
34
|
+
After the normalization and neutral-question wording changes, the complete guarded unit/integration suite passed 545 tests with no skips. The focused reviewer/recovery/evaluator run passed 83 tests, including recorded synthetic envelopes replayed through real Pi and immutable temporary Git repositories.
|
|
35
|
+
|
|
36
|
+
## Final-source GLM measurements
|
|
37
|
+
|
|
38
|
+
V11 used a full five-case run with `--max-calls 100 --max-cost 0.25 --max-output-tokens 8192 --delay-ms 3000`. A transport failure stopped it before authorization assessment generation. V12 was a separately authorized run of the remaining cases using the same limits and `--case auth,config,multifile`; this was not an automatic retry. Both used `z-ai/glm-5.3-flash`, with the output allowance including reasoning.
|
|
39
|
+
|
|
40
|
+
| Case / run | Questions | Assessment requests | Canonical verdict probes | Generated verdict probes | Total requests | Reported USD |
|
|
41
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
42
|
+
| Scoped styling / V11 | 1 | 3 | 5/5 | 2/2 | 14 | 0.023045310 |
|
|
43
|
+
| Retry deduplication / V11 | 1 | 4 | 5/5 | 2/2 | 15 | 0.020155650 |
|
|
44
|
+
| Authorization / V11 | none | 1 failed | unrun | unrun | 1 | missing |
|
|
45
|
+
| Authorization / V12 | 2 | 3 | 5/5 | 4/4 | 17 | 0.026317280 |
|
|
46
|
+
| Configuration / V12 | 1 | 3 | 5/5 | 2/2 | 14 | 0.016660060 |
|
|
47
|
+
| Twelve handlers / V12 | 3 | 8 | 5/5 | 5/6 | 25 | 0.037822720 |
|
|
48
|
+
|
|
49
|
+
Assessment requests include investigation, synthesis and the independent assessment audit. Total requests also include grading and a fresh audit for every proposed replacement question. Workspace reads are local operations and are not model requests. Verdict probe counts are separate from manual question-quality review.
|
|
50
|
+
|
|
51
|
+
Across the completed five-fixture coverage, eight generated questions received 16 generated-question probes; 15 completed as expected and one failed validation. All 25 canonical verdict probes matched. V11 plus V12 used 21 successful assessment requests, one failed assessment request, and 86 total requests: $0.124001020 reported, with cost telemetry for 85 requests. No live compaction occurred in these cases; compaction coverage is deterministic.
|
|
52
|
+
|
|
53
|
+
Manual review accepted the styling question's propagation boundary and the authorization questions' tenant boundary and indistinguishable denial/missing responses. Their automatic concept-coverage flags were vocabulary false positives; raw flags were retained. The retry questions and audited replacement keys were source-correct. One rubric mentioned process restart although the visible question did not ask it. A separate, independently written minimal-answer probe omitted restart information and was accepted as correct: one request, $0.000912350, no replacement question.
|
|
54
|
+
|
|
55
|
+
Known limitations remain: one styling feedback sentence was incomplete despite a complete structured response; an authorization replacement mostly renamed the original scenario rather than testing substantially different application of the concept. The configuration question correctly tested default/override precedence, but its wording gave away that the override was unaffected. Its wrong-answer replacements tested a useful new boundary: a set-but-empty value becomes zero instead of using the default. Passing these verdict probes does not prove grading fairness for all shorter answers, semantic correctness of every future audit, or sufficiently distinct transfer questions.
|
|
56
|
+
|
|
57
|
+
The multifile failure was retained, not converted to a pass. The independent replacement audit changed a valid ID to `permanent-id?`, which the existing validator rejected before accepting the grade or replacement. Manual inspection found a second defect in that rejected candidate: it described `await run()` without the operation argument required by the inspected handler, yet predicted three side effects from that operation. A deterministic reproduction gives zero counter increments and a `TypeError`; the audit missed the incomplete call. Its claim of no measurable delay also exceeded the source's narrower guarantee of no intentional backoff. The main exhaustion question's lack of an explicit causal-explanation request remains a quality flag. Thus the final live matrix is not all green, even though the accepted source keys and 40 completed verdict checks were consistent with the fixtures.
|
|
58
|
+
|
|
59
|
+
V11's authorization request returned HTTP 200 headers but no parsed completion or cost telemetry after approximately 180 seconds. Sphinx failed closed and issued no receipt. A deterministic aborted-body reproduction confirmed that the old transport diagnostic classified its own deadline as invalid/oversized JSON; the missing completion is not evidence of a semantic model failure. No timeout was extended for the next run.
|
|
60
|
+
|
|
61
|
+
## Focused transfer-distance follow-up
|
|
62
|
+
|
|
63
|
+
The label-only authorization transfer exposed missing input to its audit: the audit did not receive the previous public question. A narrow change now supplies that question and asks for a changed condition, ordering, boundary or prediction rather than renamed labels. This was evaluated separately; the V12 process continued using its already-loaded baseline.
|
|
64
|
+
|
|
65
|
+
Two authorized audit-only replay requests used the saved synthetic authorization evidence and candidate. At 8192 tokens, the first exhausted its output allowance, including 7675 reasoning tokens. At 16384, the second produced a source-correct new unauthenticated-caller scenario, but changed the private concept string and was rejected by the existing exact-concept validator. Neither replay produced an accepted product result. Together they cost $0.008992400; the second report's usage is cumulative and must not be added to the first. These observations support neither a claim that 8192 prevents truncation nor a claim that the transfer-distance fix passed a complete live flow.
|
|
66
|
+
|
|
67
|
+
Afterward, the output schema constrained the replacement's private concept to its existing value, matching the validator. The ID schema likewise now advertises its existing 1–80 character and allowed-character rules. Guarded evaluator/eval tests passed 45 cases. These schema fixes do not establish that the missed operation argument was semantically repaired.
|
|
68
|
+
|
|
69
|
+
## Bounded Haiku compatibility comparison
|
|
70
|
+
|
|
71
|
+
The rejected multifile key motivated one separate comparison, without changing the fixture or oracle:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
npm run eval -- --live --case multifile \
|
|
75
|
+
--model anthropic/claude-haiku-5.5 --allow-paid --max-calls 35 \
|
|
76
|
+
--max-cost 0.10 --max-output-tokens 8192 --delay-ms 3000 \
|
|
77
|
+
--out /tmp/sphinx-eval-live-multifile-haiku-v13.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
OpenRouter rejected the first request with HTTP 404 because no endpoint supported the requested `tool_choice` value. No assessment or grading ran; no cost was reported, and Sphinx did not retry. This is evidence of route incompatibility for this request, not evidence about Haiku's question quality. The process loaded the concept constraint but started before the ID schema parity change. Its same-files source fingerprint was `d133d4d15db043ee66effb38fa46f9d0413d1308997b8fc9f9f27f23d045de76`.
|
|
81
|
+
|
|
82
|
+
After the transport used Anthropic's supported automatic tool selection while retaining Sphinx's local final-tool enforcement, a separately authorized five-case V14 run used the same model, 8192 output tokens, a 100-request/$0.15 stop, and 1000ms spacing:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
npm run eval -- --live --model anthropic/claude-haiku-5.5 --allow-paid \
|
|
86
|
+
--max-calls 100 --max-cost 0.15 --max-output-tokens 8192 \
|
|
87
|
+
--delay-ms 1000 --out /tmp/sphinx-eval-live-matrix-haiku-v14.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| V14 case | Assessment requests | Accepted questions | Verdict probes | Total requests |
|
|
91
|
+
|---|---:|---:|---:|---:|
|
|
92
|
+
| Scoped styling | 4, failed | none | unrun | 4 |
|
|
93
|
+
| Retry deduplication | 4, failed | none | unrun | 4 |
|
|
94
|
+
| Authorization | 6 | 1 | 7/7 | 17 |
|
|
95
|
+
| Configuration | 4, failed | none | unrun | 4 |
|
|
96
|
+
| Twelve handlers | 5 | 2 | 9/9 | 19 |
|
|
97
|
+
|
|
98
|
+
All 48 responses explicitly reported zero cost; this records that run's telemetry and does not establish free model pricing. The 16 verdict probes comprise ten canonical and six generated probes. Independent inspection found all three accepted main keys and nine accepted replacement keys source-correct, including the missing-tenant-field boundary and retry exhaustion/recovery. Auth's prompt was somewhat leading; the unaccepted styling/configuration candidates also supplied part of their answers. One multifile replacement overlapped a different initial question. Those quality limitations remain separate from the successful verdict counts.
|
|
99
|
+
|
|
100
|
+
The three smaller cases failed on response shape before their audits: their first finish payload placed `summary` inside the `assessment` object rather than beside it. Subsequent repair attempts emitted malformed JSON strings and exhausted the bounded review allowance. A lossless normalizer was added afterward for both transports: it decodes only valid JSON-object strings and moves known metadata only when the outer field is absent. It preserves question/evidence values, unknown fields, conflicting metadata and raw native continuation; strict validation still rejects bad JSON and unread citations. Recorded first-payload fixtures exercise this fix without another live request. V14 remains failed and was not rewritten as a pass.
|
|
101
|
+
|
|
102
|
+
V14's source sidecar is `sphinx-eval-live-matrix-haiku-v14-source.json`; it adds `src/openrouter.js` to the ordered fingerprint inputs listed above. Its fingerprint is `0037ff2cfb1ac5e7cae8e05976dc43ec154dba0ba04f6bf25396c95a07d8cdf2`. The normalization change was not loaded in this run.
|
|
103
|
+
|
|
104
|
+
## Post-normalization Haiku matrix
|
|
105
|
+
|
|
106
|
+
V15 repeated the full V14 command with output `/tmp/sphinx-eval-live-matrix-haiku-v15.json`, after lossless finish-envelope normalization and neutral-question wording. Model-facing source was frozen throughout the run. The ordered source fingerprint added `src/reviewer-response.js` and was `d803245a77cdbcacc240df9fd016b42b81c4c382c2dea81dbe210752a5449224`; the full path/hash list is in the corresponding `-source.json` sidecar.
|
|
107
|
+
|
|
108
|
+
| V15 case | Assessment requests | Questions | Canonical verdict probes | Generated verdict probes | Total requests |
|
|
109
|
+
|---|---:|---:|---:|---:|---:|
|
|
110
|
+
| Scoped styling | 3 | 1 | 5/5 | 1/2 | 15 |
|
|
111
|
+
| Retry deduplication | 3 | 1 | 5/5 | 2/2 | 14 |
|
|
112
|
+
| Authorization | 2 | 2 | 4/5 | 3/4 | 15 |
|
|
113
|
+
| Configuration | 3 | 1 | 3/5 | 2/2 | 16 |
|
|
114
|
+
| Twelve handlers | 4 | 2 | 5/5 | 3/4 | 18 |
|
|
115
|
+
|
|
116
|
+
All five assessments were accepted, using 15 assessment requests. The complete run used 78 requests; all 78 explicitly reported zero cost. There was no provider failure, truncation, or automatic route change. Seven deterministic regressions also passed. This is **not** an all-green quality result: 33 of 39 verdict probes matched, and manual inspection found problems beyond verdict counts.
|
|
117
|
+
|
|
118
|
+
The styling question copied CSS and markup into a numeric-padding question and required exact pixels and specificity notation. Its key was source-correct, but it rejected the correct qualitative explanation of affected card controls and unchanged toolbar controls. Four of its five replacements repeated this numeric focus. This violates the intended behavioral-understanding scope; adding “why” to property arithmetic does not fix it.
|
|
119
|
+
|
|
120
|
+
Authorization had two product failures: a correct equivalent explanation of the shared bodyless 404 response was withheld for not naming the literal combined `if`; and a corrected invalid-key replacement repeated the original prompt, so novelty validation rejected it before the source auditor could rewrite it. The replacement already had a fresh ID, so changing IDs would not repair the issue. The other authorization question asked whether lookup occurred for an unauthenticated caller; the broad fixture answer omitted that ordering but was nevertheless accepted. This is a separate false positive and probe-coverage weakness, not a reason to accept incomplete predictions.
|
|
121
|
+
|
|
122
|
+
Two configuration failures were **fixture evidence defects**: canonical grading supplied only HEAD bodies, while its precommitted key claimed the default had increased. The source-correct generated question and both generated probes passed. The question still tested a narrower default/fallback case than the more useful default-versus-override comparison. The multifile generated failure was also a **probe-coverage gap**: the question asked for a second-call successful return, while the fixed answer described the cap and generic return-on-success without explicitly predicting that scenario. Withholding a pass was defensible. Its wrong-answer feedback did incorrectly say “exactly three” attempts while discussing a scenario that succeeds on the second; the incorrect verdict itself was justified.
|
|
123
|
+
|
|
124
|
+
Independent review found all seven accepted main keys and 24 accepted replacement keys source-correct. Retry behavior was consistently graded; one replacement omitted an explicit request for the reason, although the questionnaire's shared instructions request it. These findings do not erase the styling and grading failures.
|
|
125
|
+
|
|
126
|
+
After the frozen run, the harness was corrected to include actual filtered immutable diffs alongside HEAD dependencies for canonical probes. Source-executed fixture checks now establish unauthenticated early return before lookup and a transient retry resolving with the successful second result. The revised probes do not derive answers from model keys. Sixteen guarded eval tests passed; the V15 report remains unchanged. Focused product fixes and follow-up measurements are reported separately rather than relabeling V15.
|
|
127
|
+
|
|
128
|
+
## Focused Haiku follow-up
|
|
129
|
+
|
|
130
|
+
V16 replayed the exact saved styling candidate through the production assessment audit, then graded the same qualitative correct answer and misconception. It also checked equivalent authorization reasoning, complete and omitted lookup ordering, an invalid-key replacement, configuration probes with actual diff evidence, and transient retry probes with the independently completed answer. A scripted investigator supplied the saved candidate; its two turns were not live requests. The captured provisional invalid-key grade was likewise replayed, with only its existing source audit live. All other grading was live on fresh isolated immutable fixtures.
|
|
131
|
+
|
|
132
|
+
Ten of eleven focused checks passed using 15 actual requests, each explicitly reporting zero cost. Summed check duration was 107 seconds. The 11 checks include one assessment audit and ten grading/replacement checks; they are not eleven independently generated assessments. The source fingerprint was `6993ace15095bdd328d3c95ec8e82f8ce6ea5d2a1bbed602ac59282f90223f8c`.
|
|
133
|
+
|
|
134
|
+
The audit removed numeric arithmetic from the styling question, but Haiku still withheld a pass from the sufficient answer: “new padding” on card buttons plus unchanged horizontal padding establishes a vertical change, and the answer gave the ancestor cause and unchanged toolbar boundary. Its redundant clarification transfer was rejected by the audit. This is a remaining semantic false negative, not a successful fairness check; the conditional fresh styling-generation run was not launched.
|
|
135
|
+
|
|
136
|
+
Authorization's equivalent explanation was accepted, a complete early-return explanation passed, and omission of the explicitly requested ordering remained ambiguous. The invalid-key replacement reached the existing audit, which rewrote it into a source-correct base/head comparison; the verdict stayed ambiguous. Both configuration and transient retry checks passed. Their audited replacements were source-correct and distinct. A retry citation reason still loosely described the attempt cap as exactly three; the feedback itself correctly discussed the second-call success.
|
|
137
|
+
|
|
138
|
+
An initial temporary replay-wrapper mistake bound rebuilt source observations to the old synthetic snapshot ID. Eight remaining probes failed locally before any requests; the untouched initial artifact retains those zero-call errors. The corrected wrapper continued only the unrun probes and carried forward all five already-used styling requests. `/tmp/sphinx-eval-focused-haiku-v16.json` is cumulative and must not be added to its `-initial.json` artifact. This correction did not retry a model request or erase the styling failure.
|
|
139
|
+
|
|
140
|
+
After this measurement, an optional replacement rejected by an insufficient-evidence audit no longer turns an ambiguous grade into a provider-style failure: it keeps the original question pending with clarification feedback. Incorrect answers still require an audited transfer; provider, cancellation, context and malformed-output errors still propagate. This recovery change has deterministic coverage and does not make the false-negative answer correct. The revised scripted baseline passed five fixtures, 35 verdict probes and seven regressions with 59 fake requests; the full guarded suite before that final recovery change passed 550 tests.
|
|
141
|
+
|
|
142
|
+
## Stronger-model fairness falsification
|
|
143
|
+
|
|
144
|
+
V17 used `anthropic/claude-sonnet-5.5` with the exact saved V16 qualitative styling question, key and unchanged sufficient answer. It did not first rewrite the question to an easier one. The model returned ambiguous, requiring explicit vertical-change wording and higher-specificity terminology despite the answer establishing new card padding, unchanged horizontal padding, the ancestor scope and unchanged toolbar. This reproduced the material false negative.
|
|
145
|
+
|
|
146
|
+
The predetermined stop condition ended the comparison after that first request: 4.6 seconds, one explicitly reported zero-cost response. The planned misconception, authorization and five-fixture generation checks were **not run**. This provides no evidence that Sonnet passes the broader matrix or that increasing model cost solves the grading-design problem. The report is `/tmp/sphinx-eval-focused-sonnet-v17.json`, with source fingerprint `413f07e509a00922375faf3176aee438ce01ed8ba5dbc7b96af71643a0c3ceae`. No further route comparison followed this result.
|
|
147
|
+
|
|
148
|
+
## Explicit minimum-criteria replay
|
|
149
|
+
|
|
150
|
+
The next change separates private minimum acceptance into `acceptance.prediction` and `acceptance.causalReason`. New questions and replacement audits must produce both; fuller `expectedAnswer` and `rationale` remain independently source-checked explanations, not extra pass requirements. Grading receives those explanations in a separate `sourceKey`. Existing questions remain readable. Curated eval criteria were authored from source without changing human probes, and 17 eval tests passed. The scripted acceptance baseline passed all five fixtures and 35 verdict probes using 59 fake requests.
|
|
151
|
+
|
|
152
|
+
V18 source-audited the exact legacy V16 question through the same audit wrapper used by production generation. The audit added source-correct criteria without requiring specificity terminology. Haiku then still marked the unchanged sufficient answer ambiguous for not explicitly saying “vertical”, despite new card padding plus unchanged horizontal padding establishing that result. The criteria separation therefore has structural test coverage but **did not pass this live fairness regression**.
|
|
153
|
+
|
|
154
|
+
The run stopped after two requests and 21.5 seconds, both with explicit zero-cost telemetry. No misconception, fresh styling generation or remaining-case matrix ran because their prerequisite failed. The report is `/tmp/sphinx-eval-acceptance-haiku-v18.json`; source fingerprint `9bbcff04e1281c1178ce44f14def6f2c7e26b739abd632489060009cf7b65eaf`. The ambiguous/null result leaves the checkpoint pending and grants no approval; safe noncompletion is separate from fair grading.
|
|
155
|
+
|
|
156
|
+
## Fresh generation with minimum criteria
|
|
157
|
+
|
|
158
|
+
V19 separately tested fresh styling generation, rather than auditing the old compound candidate again. It used the first live command above. After independent review accepted that case, V20 used the second command for the four remaining fixtures. Both used `anthropic/claude-haiku-5.5`, 8192 output tokens and the same frozen source. No models, prompts or human probes changed between them. The assessment policy now includes contract version 3, so production questions and receipts prepared under the earlier contract are not silently reused.
|
|
159
|
+
|
|
160
|
+
| Case / run | Questions | Assessment requests | Generated verdict probes | Total requests |
|
|
161
|
+
|---|---:|---:|---:|---:|
|
|
162
|
+
| Scoped styling / V19 | 1 | 3 | 2/2 | 6 |
|
|
163
|
+
| Retry deduplication / V20 | 1 | 3 | 2/2 | 6 |
|
|
164
|
+
| Authorization / V20 | 2 | 3 | 3/4 | 9 |
|
|
165
|
+
| Configuration / V20 | 1 | 3 | 1/2 | 6 |
|
|
166
|
+
| Twelve handlers / V20 | 2 | 4 | 4/4 | 10 |
|
|
167
|
+
|
|
168
|
+
The two runs used 37 actual requests: 16 for assessments, 14 for grading and seven for replacement audits. All 37 explicitly reported zero cost; that is provider telemetry, not a claim that the route is free. V19 took 40.1 seconds and V20 took 241.3 seconds. There was no provider failure, truncation, live compaction or automatic retry. The source fingerprint adds `src/config.js` to the nine V15 inputs and is `d7d13eeafc213420d9f2d999c11a98751613e015eb5556a826920e98eb514661`. Corresponding source sidecars retain each file hash.
|
|
169
|
+
|
|
170
|
+
Fresh styling tested one propagation boundary: which of a card button and a toolbar button receives the changed vertical padding, and why. Its minimum criteria required the affected/unchanged surfaces and the card ancestor relationship, without numeric padding, specificity notation or an extra horizontal-axis checklist. The same unchanged qualitative answer rejected in V18 was accepted; the global-class misconception was rejected. The audited transfer placed a card inside a toolbar and correctly tested the resulting ancestor match. This is evidence for that fresh question, not a successful replay of V18.
|
|
171
|
+
|
|
172
|
+
The authorization failure is a current product false negative. The answer explained that another tenant gets a bodyless 404 “just like a missing id,” establishing the requested response equivalence. Grading still demanded an explicit “no” and the literal combined-condition mechanism. The source-audited acceptance criteria themselves unnecessarily named a single combined condition. Both question keys and accepted replacements were source-correct; source correctness did not make that sufficient answer fairly graded.
|
|
173
|
+
|
|
174
|
+
The configuration question used “BATCH_SIZE is set to 5.” The independently authored probe adapter recognized `BATCH_SIZE=number` but not this phrasing, and supplied its original example with 7. That is an uncovered scenario, so this result does not establish how the model would grade a sufficient answer to the stated input. Separately, the raw response called the omitted scenario prediction ambiguous and acknowledged no material misconception, yet emitted `incorrect` with no required transfer. Strict validation rejected that malformed result. The report remains failed; neither failure was relabeled as a pass or rerun with a tailored answer. The wrong-precedence probe was rejected correctly, and its unset-environment transfer was source-correct.
|
|
175
|
+
|
|
176
|
+
After the frozen run, the fixture adapter was extended to parse the visible “is set to” numeric assignment and mark other detected unsupported assignment forms uncovered. It still uses only the independently implemented numeric precedence rule, never a model key or criterion. This is a fixture correction with no further live measurement; V20's source fingerprint, answers and failure remain unchanged.
|
|
177
|
+
|
|
178
|
+
Retry and multifile predictions, minimum criteria and accepted replacement keys were independently checked against source. The retry transfer changes failure to success and tests the duplicate call's uncached `undefined` return. Multifile checks cover second-call success and final rejection after three total attempts; replacements test an unreachable fourth-call success and a hypothetical limit of two. The latter is a modest parameter-change transfer, but its count affects actual retry behavior. All seven accepted main keys and seven accepted replacement keys in V19/V20 were source-correct on manual review. Styling, authorization-denial and multifile-final-failure keyword flags were vocabulary false positives; their raw flags remain.
|
|
179
|
+
|
|
180
|
+
This coverage is generated-only. Earlier canonical results are retained under their original source versions, and no complete canonical matrix was rerun after contract version 3. The latest scripted acceptance baseline passed five fixtures, 35 verdict probes and seven selected regressions using 59 fake requests; eval unit tests passed 17 cases. The final guarded suite passed 560 tests with no skips. Those deterministic checks verify implementation behavior and privacy boundaries; they do not override the live semantic failures.
|
|
181
|
+
|
|
182
|
+
## Earlier failures were retained
|
|
183
|
+
|
|
184
|
+
| Run | Model | Requests | Reported USD | Observations |
|
|
185
|
+
|---|---|---:|---:|---|
|
|
186
|
+
| Initial cosmetic iterations | Qwen Coder/Next and DeepSeek | 21 | 0.011807669 | Contradictory selector key, unsupported-premise false pass, weak numeric questions, rejected audits, and 429s. |
|
|
187
|
+
| V4 | DeepSeek V3.2 | 50 | 0.073801164 | Invalid-key grading and feedback failures; run-wide allowance left the final case untested. |
|
|
188
|
+
| V5 | DeepSeek V3.2 | 17 | 0.022592460 | Cosmetic numeric recall and an audit that confused distinct retry branches. |
|
|
189
|
+
| V6 | Qwen3 Coder Next | 5 | 0.002084040 | Provider 429; no successful matrix. |
|
|
190
|
+
| V7 | DeepSeek V3.2 | 9 | 0.014308000 | Investigation/finalization exhausted the normal review ceiling. |
|
|
191
|
+
| V8 | DeepSeek V3.2 | 26 | 0.016196685 | Valid questions were marked ambiguous when the human answer was wrong; contradictory retry key. Stopped after two cases. |
|
|
192
|
+
| V9 | Qwen3 Coder | 48 | 0.035690180 | Weak/redundant authorization questions despite 11/11 verdicts; wrong answers sometimes invalidated sound keys; final case timed out. |
|
|
193
|
+
| V10 | GLM 5.3 Flash, 4096 tokens | 25 | 0.033687670 | Two cases had 7/7 verdicts each, but manual review found a replacement key that omitted a possible callback throw. Authorization audit hit the output cap, including 3736 reasoning tokens. |
|
|
194
|
+
|
|
195
|
+
The V9 generated configuration question used `BATCH_SIZE=15` while its original fixed probe answered `=7`. That mismatch was a fixture coverage defect, not proven bad grading. Subsequent probes derive explicit numeric inputs from the visible question and the independently implemented loader rule, never from a model's answer key. The separate V9 canonical wrong-answer-to-ambiguous failure remains a product failure.
|
|
196
|
+
|
|
197
|
+
The observed defects led to bounded source inventory/diff seeding, a single repair window within the existing allowance, source-constrained citations, source-first question-validity grading, and independent audits of replacement questions. These fixes did not retroactively change earlier results. No model's assertion that its own question is good was used as the quality oracle.
|
|
198
|
+
|
|
199
|
+
## Artifacts and accounting
|
|
200
|
+
|
|
201
|
+
Raw reports remain local under `/tmp`, not in the repository. They contain only synthetic source, questions and rubrics, and sanitized diagnostics; no credentials. The two confirmed sufficient-answer failures from V18 and V20 are also retained in [a small regression fixture](fixtures/known-false-negatives.json), including exact source definitions, question criteria, answers and provenance. Main reports are `sphinx-eval-scripted-final.json`, `sphinx-eval-live-matrix-glm-v11.json`, `sphinx-eval-live-remaining-glm-v12.json`, and `sphinx-eval-retry-fairness-v11.json`. The focused audit reports are `sphinx-eval-auth-transfer-replay-v12.json` and `sphinx-eval-auth-transfer-replay-16384-v12.json`; the compatibility comparison is `sphinx-eval-live-multifile-haiku-v13.json`. Earlier comparisons use `sphinx-eval-live-matrix-deepseek-v4.json`, `sphinx-eval-live-small-deepseek-v5.json`, `sphinx-eval-live-matrix-qwen-v6.json`, `sphinx-eval-live-small-deepseek-v7.json`, `sphinx-eval-live-matrix-deepseek-v8.json`, `sphinx-eval-live-matrix-qwen-coder-v9.json`, and `sphinx-eval-live-matrix-glm-v10.json`. The initial cosmetic reports are `sphinx-eval-live-cosmetic.json`, `sphinx-eval-live-cosmetic-v2.json`, `sphinx-eval-live-cosmetic-v3.json`, `sphinx-eval-live-cosmetic-qwen-coder.json`, and `sphinx-eval-live-cosmetic-deepseek.json`.
|
|
202
|
+
|
|
203
|
+
The latest reports are `sphinx-eval-live-cosmetic-haiku-v19.json` and `sphinx-eval-live-remaining-haiku-v20.json`, with matching `-source.json` sidecars. The acceptance baseline is `sphinx-eval-scripted-acceptance.json`. Focused reports V16–V18 remain `sphinx-eval-focused-haiku-v16.json`, `sphinx-eval-focused-sonnet-v17.json` and `sphinx-eval-acceptance-haiku-v18.json`; V15 is `sphinx-eval-live-matrix-haiku-v15.json`.
|
|
204
|
+
|
|
205
|
+
All listed exploratory live runs through V20, the fairness probe and the two audit replays total **472 actual requests and $0.344073638 reported**, with cost telemetry for 465 requests and seven missing reports. The V12 remaining-case run alone used 56 requests and $0.080800060, all reported. Missing telemetry is not assumed to mean a free request; reported totals are not a billing reconciliation. Scripted requests are excluded from these totals.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"scope": "Synthetic fixture questions and authored answers only. These are known failures, not passing model assertions.",
|
|
4
|
+
"cases": [
|
|
5
|
+
{
|
|
6
|
+
"id": "v18-cosmetic-sufficient-qualitative-answer",
|
|
7
|
+
"source": {
|
|
8
|
+
"caseId": "cosmetic",
|
|
9
|
+
"requiredPaths": [
|
|
10
|
+
"styles.css",
|
|
11
|
+
"index.html"
|
|
12
|
+
],
|
|
13
|
+
"definition": {
|
|
14
|
+
"context": "A task application shares the button class between task-card actions and toolbar actions. This patch should change only card buttons, without changing toolbar controls or click behavior.",
|
|
15
|
+
"before": {
|
|
16
|
+
"styles.css": ".button { padding-block: 4px; padding-inline: 12px; }\n",
|
|
17
|
+
"index.html": "<main><nav class=\"toolbar\"><button class=\"button\">Refresh</button></nav><article class=\"card\"><button class=\"button\">Complete task</button></article></main>\n"
|
|
18
|
+
},
|
|
19
|
+
"after": {
|
|
20
|
+
"styles.css": ".button { padding-block: 4px; padding-inline: 12px; }\n.card .button { padding-block: 8px; }\n"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"definitionSha256": "50723ddddf259d210e5ce53f4c64bfdf4a0cbc7df6e656aafa0b897da3332085"
|
|
24
|
+
},
|
|
25
|
+
"question": {
|
|
26
|
+
"id": "card-button-padding-scope-qual",
|
|
27
|
+
"concept": "Scoped descendant selector overriding a shared class across two surfaces",
|
|
28
|
+
"prompt": "The styles.css diff adds a `.card .button` rule after the base `.button` rule, which sets padding on both axes. index.html has a `.button` inside `nav.toolbar` (Refresh) and a `.button` inside `article.card` (Complete task). For each button, predict whether its vertical padding and its horizontal padding change compared with before the patch, then briefly explain which selector and markup facts determine each outcome.",
|
|
29
|
+
"choices": [],
|
|
30
|
+
"evidence": [
|
|
31
|
+
{
|
|
32
|
+
"path": "styles.css",
|
|
33
|
+
"reason": "The diff adds a `.card .button` rule after the base `.button` rule and declares only the block-direction padding in the new rule, so overriding applies to one axis only."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "index.html",
|
|
37
|
+
"reason": "Refresh is inside nav.toolbar, outside article.card, so the descendant selector cannot match it; Complete task is inside article.card, so it matches."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"acceptance": {
|
|
41
|
+
"prediction": "Complete task's block-direction (vertical) padding changes while its inline-direction (horizontal) padding stays the same, and Refresh's padding changes on neither axis.",
|
|
42
|
+
"causalReason": "The .card .button rule matches only the button inside article.card and sets only block-direction padding, so it overrides the base .button value on that axis while the base rule still supplies inline padding."
|
|
43
|
+
},
|
|
44
|
+
"expectedAnswer": "Complete task (inside .card): its vertical padding changes, and its horizontal padding does not. The later .card .button rule matches it and has higher specificity than .button, so it wins for the block axis; that rule sets only padding-block, so the inline axis still comes from the base .button rule. Refresh (in nav.toolbar, outside .card): neither axis changes, because .card .button requires a .card ancestor and only the base .button rule matches it.",
|
|
45
|
+
"rationale": "Causal claims: (1) the new rule is scoped by the .card ancestor, so the toolbar button outside article.card does not match; (2) the descendant selector's higher specificity beats the base .button rule for padding-block where both apply; (3) padding-inline is unchanged because the new rule declares only padding-block, so the base rule still supplies it for the card button. The question asks for a qualitative per-axis prediction and cause, not exact values or specificity numbers. Evidence: the styles.css diff adds the .card .button rule after the base .button rule and sets only padding-block in the new rule; index.html places Refresh in nav.toolbar and Complete task inside article.card."
|
|
46
|
+
},
|
|
47
|
+
"answer": "Only buttons inside a card receive the new padding because the new selector requires a card ancestor. The toolbar button shares the button class but is outside a card, so its styling stays unchanged. The base button rule, horizontal padding, and click behavior remain unchanged.",
|
|
48
|
+
"expectedVerdict": "correct",
|
|
49
|
+
"observedVerdict": "ambiguous",
|
|
50
|
+
"observedFeedback": "The question, criteria, and sourceKey match the source: .card .button sets only padding-block, so Complete task's vertical padding changes while its horizontal padding stays from the base rule, and Refresh is unaffected. The answer correctly says the toolbar button and horizontal padding are unchanged and that the new selector needs a card ancestor. It never states that the vertical (block-direction) padding is what changes for Complete task, so the required per-axis prediction is missing. Please state which axis changes for the card button and why.",
|
|
51
|
+
"independentFinding": "New card padding together with unchanged horizontal padding communicates the vertical change. The answer also explains the card ancestor and unchanged toolbar boundary; requiring the literal word vertical is a false negative.",
|
|
52
|
+
"provenance": {
|
|
53
|
+
"run": "V18",
|
|
54
|
+
"artifact": "sphinx-eval-acceptance-haiku-v18.json",
|
|
55
|
+
"completedAt": "2026-10-15T23:22:29.682Z",
|
|
56
|
+
"model": "anthropic/claude-haiku-5.5",
|
|
57
|
+
"maxOutputTokens": 8192,
|
|
58
|
+
"sourceSha256": "9bbcff04e1281c1178ce44f14def6f2c7e26b739abd632489060009cf7b65eaf",
|
|
59
|
+
"note": "Exact legacy V16 candidate after the V18 minimum-criteria audit; not replaced with the later fresh V19 question."
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "v20-auth-sufficient-response-equivalence",
|
|
64
|
+
"source": {
|
|
65
|
+
"caseId": "auth",
|
|
66
|
+
"requiredPaths": [
|
|
67
|
+
"auth/document.js"
|
|
68
|
+
],
|
|
69
|
+
"definition": {
|
|
70
|
+
"context": "A multi-tenant document service. A signed-in user may read only documents belonging to their tenant. Missing documents and denied documents share a 404 response.",
|
|
71
|
+
"before": {
|
|
72
|
+
"auth/document.js": "export function getDocument(user, id, documents) { if (!user) return { status: 401 }; const doc = documents.get(id); return doc ? { status: 200, body: doc.text } : { status: 404 }; }\n"
|
|
73
|
+
},
|
|
74
|
+
"after": {
|
|
75
|
+
"auth/document.js": "export function getDocument(user, id, documents) { if (!user) return { status: 401 }; const doc = documents.get(id); if (!doc || doc.tenantId !== user.tenantId) return { status: 404 }; return { status: 200, body: doc.text }; }\n"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"definitionSha256": "4ed2d01d0cf01d73223c0d35d52961e954818a6394605c1dd78cc0ad886da846"
|
|
79
|
+
},
|
|
80
|
+
"question": {
|
|
81
|
+
"id": "missing-vs-denied-indistinguishable",
|
|
82
|
+
"concept": "Missing vs. denied response equivalence",
|
|
83
|
+
"prompt": "Can a signed-in user tell a nonexistent document ID apart from an existing document owned by another tenant by the getDocument response? Answer yes or no and give a short reason.",
|
|
84
|
+
"choices": [],
|
|
85
|
+
"expectedAnswer": "No. Both produce the identical { status: 404 } object with no body, because the missing-document case (!doc) and the cross-tenant case (doc.tenantId !== user.tenantId) are combined in one condition and return the same value.",
|
|
86
|
+
"rationale": "The combined condition returns the same { status: 404 } for both cases, matching the project context that missing and denied documents share a 404. The 401 check runs before the lookup, so unauthenticated callers get 401 regardless of whether the ID exists; that boundary is not asked here.",
|
|
87
|
+
"evidence": [
|
|
88
|
+
{
|
|
89
|
+
"path": "auth/document.js",
|
|
90
|
+
"reason": "The combined `!doc || doc.tenantId !== user.tenantId` condition returns the same { status: 404 } for both cases."
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"acceptance": {
|
|
94
|
+
"prediction": "No, both cases return the same 404 response.",
|
|
95
|
+
"causalReason": "The single combined condition returns the same { status: 404 } for a missing doc and a tenant mismatch."
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"answer": "A signed-in user can read only a document with the same tenantId. A different tenant gets 404 without document contents, just like a missing id. A caller without a user gets 401 before any document lookup or tenant comparison, because the missing-user guard returns first. Knowing an id or being authenticated is not enough to cross the tenant boundary.",
|
|
99
|
+
"expectedVerdict": "correct",
|
|
100
|
+
"observedVerdict": "ambiguous",
|
|
101
|
+
"observedFeedback": "The source supports the question and its criteria. The combined condition returns the same { status: 404 } for a missing document and a cross-tenant document, so the response does not distinguish them. The answer states that a different tenant gets 404 \"just like a missing id,\" which conveys the outcome, but it never gives an explicit yes or no and does not explain the causal mechanism: that one combined check (!doc || doc.tenantId !== user.tenantId) returns the same value for both cases. Please clarify whether the answer is no and why the single combined condition produces identical responses.",
|
|
102
|
+
"independentFinding": "A bodyless 404 for a different tenant just like a missing id communicates response equivalence and its causal basis. Naming one combined if statement or adding an explicit no is unnecessary.",
|
|
103
|
+
"provenance": {
|
|
104
|
+
"run": "V20",
|
|
105
|
+
"artifact": "sphinx-eval-live-remaining-haiku-v20.json",
|
|
106
|
+
"completedAt": "2026-10-15T23:34:17.636Z",
|
|
107
|
+
"model": "anthropic/claude-haiku-5.5",
|
|
108
|
+
"maxOutputTokens": 8192,
|
|
109
|
+
"assessmentContract": 3,
|
|
110
|
+
"sourceSha256": "d7d13eeafc213420d9f2d999c11a98751613e015eb5556a826920e98eb514661",
|
|
111
|
+
"note": "Freshly generated and source-audited question with minimum acceptance criteria; failure occurred on the current contract."
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Local UI fixture only: no real Git operation, provider, credentials, or home edits.
|
|
2
|
+
import { mkdtemp, mkdir, rm } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
7
|
+
import { createBrowserInterview } from '../src/browser-interview.js';
|
|
8
|
+
import { createSessionStore } from '../src/sessions.js';
|
|
9
|
+
import { DEFAULT_CONFIG } from '../src/config.js';
|
|
10
|
+
|
|
11
|
+
const home = await mkdtemp(path.join(tmpdir(), 'sphinx-browser-demo-'));
|
|
12
|
+
const repoRoot = path.join(home, 'example-project'); await mkdir(repoRoot);
|
|
13
|
+
const env = { SPHINX_HOME: path.join(home, 'state'), SPHINX_USER_HOME: home }, config = structuredClone(DEFAULT_CONFIG);
|
|
14
|
+
const snapshot = { id: 'd'.repeat(64), repoRoot, event: 'pre-push', target: { ref: 'refs/heads/main' }, files: ['src/queue.js'], stats: { additions: 23, deletions: 0, files: 1 } };
|
|
15
|
+
const question = { id: 'duplicate', concept: 'Duplicate requests', prompt: 'A job finishes successfully, but the caller times out before receiving the response. If the caller retries with the same job ID in the same process, will this change prevent the job from running twice? Explain why.', choices: [], expectedAnswer: 'The process-local set rejects a duplicate until the process restarts.', rationale: 'The set is held in memory.', evidence: [{ path: 'src/queue.js', reason: 'Process-local membership is checked before execution.' }] };
|
|
16
|
+
const store = createSessionStore({ env,
|
|
17
|
+
generate: async (_snapshot, _config, { beforeCall }) => { await beforeCall(); await delay(300); return { questions: [question] }; },
|
|
18
|
+
grade: async request => { await request.beforeCall(); await delay(500); return request.learn || request.dispute || /wrong/i.test(request.answer)
|
|
19
|
+
? { verdict: request.dispute ? 'ambiguous' : 'incorrect', feedback: 'This set lives in one process. It remembers IDs while that process is running; a restart creates an empty set.', followUp: { ...question, id: randomUUID(), prompt: 'The process restarts after completing a job. The caller retries that job ID. Can the same job run again, and why?' } }
|
|
20
|
+
: { verdict: 'correct', feedback: 'You connected the behavior to the lifetime of the stored IDs.', followUp: null }; },
|
|
21
|
+
});
|
|
22
|
+
await store.ensure(snapshot, config);
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
process.on('SIGINT', () => controller.abort()); process.on('SIGTERM', () => controller.abort());
|
|
25
|
+
const interview = createBrowserInterview({ env, signal: controller.signal, store, readConfig: async () => config, revalidate: async () => true, openBrowser: async () => false, output: console.log });
|
|
26
|
+
console.log('Sphinx browser UI fixture. No real repository, model, or Git approval is involved.');
|
|
27
|
+
try { console.log(await interview.present({ request: { id: snapshot.id, repoRoot, token: randomUUID(), createdAt: Date.now(), delivery: 'hook' } })); }
|
|
28
|
+
finally { await delay(500); await interview.close(); await rm(home, { recursive: true, force: true }); }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"enabled": true,
|
|
4
|
+
"provider": "openrouter",
|
|
5
|
+
"model": "anthropic/claude-haiku-5.5",
|
|
6
|
+
"level": "standard",
|
|
7
|
+
"mode": "block",
|
|
8
|
+
"events": [
|
|
9
|
+
"pre-push"
|
|
10
|
+
],
|
|
11
|
+
"branches": [
|
|
12
|
+
"main",
|
|
13
|
+
"master"
|
|
14
|
+
],
|
|
15
|
+
"remotes": [
|
|
16
|
+
"*"
|
|
17
|
+
],
|
|
18
|
+
"exclude": [],
|
|
19
|
+
"maxContextBytes": 100000,
|
|
20
|
+
"timeoutSeconds": 180,
|
|
21
|
+
"receiptHours": 24,
|
|
22
|
+
"maxModelCalls": null,
|
|
23
|
+
"maxOutputTokens": 8192,
|
|
24
|
+
"allowPaid": true,
|
|
25
|
+
"agentMaxTurns": null,
|
|
26
|
+
"toolResultBytes": 16000,
|
|
27
|
+
"backgroundPreparation": true,
|
|
28
|
+
"preparationDebounceMs": 1500,
|
|
29
|
+
"models": {
|
|
30
|
+
"small": {
|
|
31
|
+
"provider": "openrouter",
|
|
32
|
+
"model": "anthropic/claude-haiku-5.5"
|
|
33
|
+
},
|
|
34
|
+
"medium": {
|
|
35
|
+
"provider": "openrouter",
|
|
36
|
+
"model": "anthropic/claude-haiku-5.5"
|
|
37
|
+
},
|
|
38
|
+
"large": {
|
|
39
|
+
"provider": "openrouter",
|
|
40
|
+
"model": "anthropic/claude-haiku-5.5"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"routing": {
|
|
44
|
+
"smallMaxLines": 80,
|
|
45
|
+
"smallMaxFiles": 3,
|
|
46
|
+
"largeMinLines": 400,
|
|
47
|
+
"largeMinFiles": 12,
|
|
48
|
+
"riskPatterns": [
|
|
49
|
+
"auth",
|
|
50
|
+
"permission",
|
|
51
|
+
"migration",
|
|
52
|
+
"billing",
|
|
53
|
+
"payment",
|
|
54
|
+
"crypto",
|
|
55
|
+
"security",
|
|
56
|
+
"terraform"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sphinx-understand",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Outsource your thinking, not your understanding. A comprehension checkpoint for agent-assisted development.",
|
|
5
|
+
"homepage": "https://github.com/parthh01/sphinx#readme",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/parthh01/sphinx.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/parthh01/sphinx/issues"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"bin": {
|
|
15
|
+
"sphinx": "bin/sphinx.js"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=22.19.0"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "node scripts/run-suite.mjs",
|
|
22
|
+
"check": "node --check bin/sphinx.js && node scripts/run-suite.mjs",
|
|
23
|
+
"start": "node bin/sphinx.js",
|
|
24
|
+
"eval": "node eval/run.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"bin",
|
|
28
|
+
"src",
|
|
29
|
+
"docs",
|
|
30
|
+
"eval/RESULTS.md",
|
|
31
|
+
"eval/fixtures/known-false-negatives.json",
|
|
32
|
+
"examples",
|
|
33
|
+
".sphinxconfig.example",
|
|
34
|
+
".sphinxignore.example",
|
|
35
|
+
"README.md",
|
|
36
|
+
"CONTRIBUTING.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"keywords": [
|
|
41
|
+
"git",
|
|
42
|
+
"hooks",
|
|
43
|
+
"codex",
|
|
44
|
+
"claude-code",
|
|
45
|
+
"learning",
|
|
46
|
+
"code-review"
|
|
47
|
+
],
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@earendil-works/pi-ai": "1.2.0",
|
|
50
|
+
"@earendil-works/pi-coding-agent": "1.2.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { runActivationTerminal } from './activation.js';
|
|
2
|
+
|
|
3
|
+
try {
|
|
4
|
+
const result = await runActivationTerminal({ recordFile: process.argv[2], token: process.argv[3] });
|
|
5
|
+
process.exitCode = result.code;
|
|
6
|
+
if (result.status === 'failed') process.stderr.write('Sphinx could not start this coding client. Open it manually in this repository.\n');
|
|
7
|
+
} catch {
|
|
8
|
+
process.stderr.write('Sphinx could not start this coding client. Run sphinx activate to try again.\n');
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
}
|