Calibration¶
Why solumbe grades its own risk signals against repository history, and why that does not require a model.
solumbe's gate scores a change partly on risk flags: does this diff touch authentication, money flow, a data model, a migration. Each flag carries a weight, and those weights were originally chosen by judgement.
A risk level that has never been compared to an outcome is a heuristic wearing a number. This page is the record of comparing them, on real repositories, and of what the comparison changed.
The source is TypeSafe's System One launch (announcement, concepts). Its argument is that software should not ask a model for prose and then parse it; it should ask narrow typed questions and receive calibrated probabilities: numbers trained against outcomes, so a 0.9 means roughly nine times in ten. The accompanying guidance is equally pointed: route on confidence, escalate what falls below a threshold, and let deterministic code keep control flow.
The obvious reading is "solumbe should call that model." The useful reading is the question it raises about solumbe itself:
Is solumbe's own risk score calibrated?
It had never been checked. The first attempt, recorded below, said more about
the measurement than about the score; the second one, with the join that
attempt proved was load-bearing, found a flag carrying weight it had not
earned, and a band ordering that was inverted. Both are now fixed, and the
question is answerable on demand rather than by argument: solumbe calibrate.
Partly, then. For the flags a repository has enough history to grade, and not otherwise, which is itself a result this document takes seriously.
The thesis in one line¶
A risk level that has never been compared to an outcome is a heuristic wearing a number. solumbe's evidence is already deterministic and replayable; calibration makes it accountable: every flag carries a hit rate measured on this repository's own history.
The substrate solumbe already has¶
| Calibration needs | solumbe's existing answer |
|---|---|
| A signal worth grading | inferRisk flags and level (src/lib/pr-review.js), classifyPath (src/lib/risk-paths.js) |
| Ground truth without a labelling budget | Git history: reverts, follow-up fixes to the same lines, CI outcome |
| Inputs that recompute identically | The gate is a pure function of repo state (determinism thesis) |
| A tamper-evident identity per evaluation | Receipts over canonical, timestamp-free payloads (src/lib/converge.js) |
| Somewhere to publish the numbers | Evaluation guide and the eval:accuracy / eval:harness / eval:gate scripts |
| Dimensions to segment by | CODEOWNERS, risk paths, file kinds, code map fan-out |
Nothing here needs a network, a key, or a vendor. The measurement is the same kind of object solumbe already ships: a deterministic function of repository state, recorded in a receipt.
What is asserted today¶
inferRisk sums hand-chosen weights (request surface +2, frontend/backend
contract +2, data model +3, auth/security +3, money flow +3, configuration +2,
large file diff +2, large PR +2, no test files changed +2, open discussion up to
+3, tests present −1), and then cuts the total into bands at ≥ 9 high and
≥ 4 medium.
Every one of those numbers was chosen by judgement. That is a perfectly good way to start, and a poor thing to leave permanently unexamined. The gate is reproducible, which means a wrong weight is reproducibly wrong.
The method¶
1. Outcomes, defined deterministically and reported separately¶
Three proxies, each computable from git alone:
- Reverted: a later commit that reverts this one (revert trailer or recorded sha).
- Repaired: a later commit within a bounded window that touches the same files, overlapping the same lines, and classifies as a fix.
- Rejected: in PR mode, a failing required check or a changes-requested review on the head sha.
These are proxies, not truth. A refactor that revisits the same lines is not a repair; a revert can be a product decision. They are therefore reported separately and named, never merged into a single "bug" label.
2. The backtest¶
Walk the repository's own history. For each commit (or merged PR), recompute the risk flags and level from the state at that time, then join to the outcomes above. Local, offline, and replayable, the same properties the gate already has.
3. The metrics¶
Per flag: base rate, hit rate, and lift over base rate. Per level: the confusion
matrix, and the ordering check that actually matters, are high changes
empirically worse than medium, and medium worse than low? A flag that
fires often and predicts nothing is noise; a flag that fires rarely and predicts
strongly deserves more weight than it has.
The per-flag hit rate is itself an empirical probability, P(outcome | flag). That is calibration, arrived at without a model.
4. The calibration receipt¶
Same discipline as the convergence and validation receipts: a canonical, timestamp-free payload recording the commit range, the window, the outcome definitions, the counts, and the resulting rates, so a number in a README can be traced to the run that produced it.
First measurement (2026-09-19)¶
A throwaway prototype ran the repaired proxy over this repository (283
commits since 2026-05-18, 192 non-merge, 152 scoreable) using a deliberately
weaker join than the one specified above: same file, not same lines.
reverted has no events. Not one revert in the repository's history, so
that proxy cannot be validated here in either direction.
A file-level repaired join measures co-change, not repair. The base rate
tracks the window almost linearly:
| Window | 3 days | 7 days | 14 days | 30 days |
|---|---|---|---|---|
| Repaired | 22.9% | 30.1% | 54.6% | 71.2% |
A defect signal should not triple as the window widens. Wait long enough in an active repository and some fix touches every file. This is the evidence that the line-overlap requirement above is load-bearing rather than decorative.
This repository cannot calibrate this repository. Per-flag counts:
| Flag | n | Repaired | Lift |
|---|---|---|---|
| configuration | 89 | 64.0% | 1.17x |
| auth/security | 2 | 50.0% | 0.92x |
| data model | 3 | 33.3% | 0.61x |
| money flow | 1 | 0.0% | n/a |
| (no flag) | 63 | 41.3% | 0.76x |
Every lift sits within noise of 1x, and the three flags the gate weights most heavily carry n = 2, 3 and 1. Nothing can be concluded about them from this corpus, in either direction.
One finding survives the sample-size problem: configuration fires on 89 of the
152 scoreable commits, 59%, contributing +2 to the risk score nearly every
time. A flag that fires on most changes carries little information whatever
calibration eventually says about it.
Second corpus (2026-09-19)¶
The configuration finding above was the one result the first measurement could
support, so it was the first thing checked against a second repository:
bashbop-api, a production service with 2,680 commits, 2,303 non-merge, 1,064
scoreable, seven times solumbe's corpus.
It reproduces, and sharpens.
| solumbe | bashbop-api | |
|---|---|---|
| Scoreable commits | 152 | 1,064 |
configuration fires on |
63.2% | 56.8% |
A flag firing on well over half of all changes is therefore not an artifact of solumbe's own young, chore-heavy history. Decomposing each firing by its sole cause says what is actually driving it:
| Sole cause of the firing | bashbop-api | solumbe |
|---|---|---|
| Dependency manifest / lockfile | 83% | 61% |
| CI workflow | 4% | 18% |
| First-party application config | 6% | 4% |
| Mixed causes | 6% | 15% |
configuration is, in practice, a dependency-bump detector. On bashbop-api,
five firings in six are a lockfile or a manifest and nothing else.
One caveat keeps this honest: the corpus is a second repository, not a representative sample of repositories. Two is better than one and still not many.
What was changed, and what was not¶
The loose path matching that contributed to the rate was narrowed: "config",
"lock" and "env" matched as bare word tokens, and "package.json" as a raw
substring, so ordinary source modules and every nested fixture manifest flagged.
Anchoring those removed 20 of 35 matching paths on solumbe and 7 of 58 on
bashbop-api, with nothing newly matched and no risk band changed in either.
The rate barely moved: 65.1% → 63.2% on solumbe, 56.8% → 56.7% on bashbop-api.
That is the useful part of the result. The breadth was real and worth fixing, but it was never what made the flag fire on most changes. Dependency-manifest churn is, which is a claim about outcomes, and therefore one the base rate could not settle. So it was measured.
A note on the numbers¶
The sections above were produced by a prototype, before solumbe calibrate
existed. Its scoreable filter excluded any commit with the word "fix"
anywhere in the subject; the shipped command matches a fix:-style prefix
instead. That is why bashbop-api appears as 1,064 scoreable commits in the
base-rate section and 1,178 from here onward, the same repository under
two slightly different definitions of "a commit that could be graded".
The prototype figures are left as they were measured rather than retro-fitted, because rewriting a recorded measurement to match a later tool is how a record stops being one. Everything from this point on is reproducible with the shipped command, and each run carries a receipt:
The first calibration (2026-09-19)¶
The line-overlap join specified above was implemented and run against bashbop-api: 1,178 scoreable commits, 1,066 fix commits, 936 joined to a parent. For each fix, blame the exact pre-image lines it modifies at its parent; the commits owning those lines are the ones it repairs.
The join matters more than any number it produces. Against the same corpus, the file-level join the first measurement used behaves completely differently:
| Join | 3 days | 30 days | 90 days |
|---|---|---|---|
| same file | 38.3% | 79.5% | 91.4% |
| line overlap | 12.0% | 24.0% | 30.7% |
At 90 days the file-level join calls 91% of all commits repaired. A proxy that fires on nearly everything cannot separate anything, which is why the first measurement could conclude so little. The line-overlap join leaves roughly seven commits in ten unrepaired, and discriminates.
configuration was two signals wearing one name¶
Base rate 25.8%, 30-day window:
Subset of configuration |
n | repaired | lift |
|---|---|---|---|
| manifest / lockfile only | 513 | 10.7% | 0.42x |
| includes a real config file | 107 | 52.3% | 2.03x |
| combined, as it shipped | 620 | 17.9% | 0.69x |
A 4.8x separation, stable at every window from 7 to 90 days. Merged, the two destroyed each other: the combined flag scored below even the commits carrying no flag at all. Real configuration predicts repair about as strongly as auth/security does; dependency churn does not predict it at all. (An earlier revision of this section called dependency churn measurably safer than an average change. A third corpus put it at 1.05x (see below), so the claim that survives is the weaker one: no consistent signal, in either direction.)
The bands were mis-sorted¶
This is the finding that made the change urgent rather than tidy. Band
ordering was non-monotonic at every window: medium changes were
consistently less likely to be repaired than low, because +2 from a
lockfile bump pushed hundreds of otherwise-low commits into medium:
| Window | before (low / med / high) | after |
|---|---|---|
| 7d | 17.3% / 11.7% / 34.8% | 6.7% / 28.4% / 33.8% |
| 30d | 26.9% / 17.3% / 53.2% | 10.1% / 42.1% / 52.6% |
| 90d | 34.1% / 23.4% / 63.1% | 12.8% / 56.8% / 61.7% |
A gate whose medium is safer than its low is mis-sorting changes whatever
its per-flag numbers say. Dependency manifests now carry a dependency flag
of their own, scored at zero, still surfaced as evidence, because a reviewer
wants to see a lockfile moved, but no longer inflating the score.
What the surviving weights look like¶
With dependency churn separated out, every remaining flag lands where its weight roughly implies:
| Flag | n | repaired | lift | weight |
|---|---|---|---|---|
| money flow | 64 | 62.5% | 2.42x | +3 |
| auth/security | 186 | 58.1% | 2.25x | +3 |
| configuration | 107 | 52.3% | 2.03x | +2 |
| request surface | 410 | 51.7% | 2.00x | +2 |
| large file diff | 209 | 49.3% | 1.91x | +2 |
| data model | 230 | 46.5% | 1.80x | +3 |
| dependency | 545 | 13.8% | 0.53x | +0 |
Whether request surface deserves more than data model is a real question
this corpus raises and does not settle. Nothing else was touched: calibration
grades the signal, it does not tune it, and a measured weight is still a
human-reviewed code change.
A third corpus, and two claims it revises (2026-09-19)¶
bashbop-event-web (2,027 non-merge commits, 1,026 scoreable, 977 fix
commits) was measured next, chosen because it is a frontend repository.
A question about request surfaces answered only on an API is a question
answered on one kind of code.
Its base rate is 47.1%, nearly double bashbop-api's 25.8%: roughly half of all commits in it announce themselves as fixes. Lift compresses toward 1.0 as the base rate rises, so the magnitudes are not comparable across the two corpora, only the ordering is.
| Flag | n | repaired | lift | weight |
|---|---|---|---|---|
| data model | 51 | 70.6% | 1.50x | +3 |
| large file diff | 329 | 69.0% | 1.47x | +2 |
| configuration | 149 | 63.8% | 1.35x | +2 |
| auth/security | 144 | 61.1% | 1.30x | +3 |
| request surface | 515 | 60.8% | 1.29x | +2 |
| frontend/backend contract | 175 | 60.6% | 1.29x | +2 |
| dependency | 234 | 49.6% | 1.05x | +0 |
| money flow | 53 | 47.2% | 1.00x | +3 |
| (no flag) | 223 | 29.1% | 0.62x | n/a |
The band ordering holds. Monotonic again, at low 35.4%, medium 63.3% and high 76.1%, on a repository that had no part in the change that fixed it. That is the first genuinely independent check on the correction above.
The open weight question closes, in favour of leaving it alone. On
bashbop-api request surface (+2) outranked data model (+3), which looked
like an argument for re-weighting. Here the order is reversed and data model
is the strongest flag in the table while request surface sits near the
bottom. The inversion does not replicate; it was one repository's shape, an
API whose data model is stable and whose routes churn, not a property of the
signals. The current weights stand.
A claim made here last iteration was too strong. dependency was
described as measurably safer than an average change. It lifts 1.05x on this
corpus: indistinguishable from average, not safer. What survives both is the
weaker and more useful claim: dependency churn carries no consistent
signal, 0.53x in one repository and 1.05x in another, predictive in neither
direction. Zero is still the right weight; "safer" was one corpus talking.
That correction is the method working rather than a lapse in it. A rate from a single repository is a hypothesis, and the thesis says so; this is what it looks like when the second one disagrees.
Ship the instrument, not just the number¶
All of the above now comes from solumbe calibrate <repo>, not a scratch
script, with the minimum-sample rule enforced in code rather than by hand,
and a receipt over a canonical timestamp-free payload so every number here can
be traced to the run that produced it.
Pointed at solumbe itself, the command mostly declines to answer:
| money flow | +3 | 1 | withheld (n < 30) | n/a |
| auth/security | +3 | 2 | withheld (n < 30) | n/a |
| data model | +3 | 3 | withheld (n < 30) | n/a |
Monotonic (low < medium < high): unknown (a band fell below the minimum sample)
That is the rule working. This repository still cannot calibrate this repository, and the tool now says so rather than printing a decimal.
Grading the verdict, not only the flags (2026-10-10)¶
Everything above grades the risk flags, which are one input to the gate. It
does not grade what the gate says with them, and it cannot say whether showing
a verdict changes what happens next. Those are three different questions, and
solumbe calibrate now answers each with its own instrument.
| Question | Command | Evidence | What it cannot show |
|---|---|---|---|
| Does a WARN or FAIL change get repaired more often than a PASS one? | solumbe calibrate <repo> --gate |
History: the real gate and convergence score replayed on each commit, joined to repaired |
Whether the gate prevented anything |
| When a check warns, does anyone act on it? | solumbe calibrate <repo> --follow-through |
The local usage log: the next run on the same repository | Whether the next run was the same change |
| Does showing the checks reduce repairs? | solumbe calibrate <repo> --trial |
A trial with a control arm, SOLUMBE_CHECK_MODE=trial |
Anything, until both arms hold 30 graded changes |
A check whose warnings do not predict a repair and are rarely cleared is a false alarm. Neither of the first two numbers says that alone, and only the third is evidence of an effect.
The first replay¶
The command was pointed at this repository on the branch that introduced it: 314 non-merge commits, 111 replayed. Fix commits are the outcome, and release, docs-only and under-30-day commits are not graded.
| Verdict | n | repaired | 95% interval | lift |
|---|---|---|---|---|
| PASS | 81 | 16.0% | 9.6% to 25.5% | 0.74x |
| WARN | 30 | 36.7% | 21.9% to 54.5% | 1.70x |
| FAIL | 0 | withheld | — | — |
The gate raised an alarm on 27.0% of changes (19.6% to 36.0%). Before the review-state check stopped warning in local mode that figure was 100%, and there was no PASS row to compare against. Of the 30 alarms, 19 were on a change nothing later repaired: 63.3% (45.5% to 78.1%).
The direction is the one a useful gate would show. The claim is not earned:
the two intervals overlap, so on this corpus WARN is not shown to differ from
PASS. Risk review warned on 26 changes and Dependency audit on 6, both
under the minimum sample, so neither has a published rate. The convergence
bands read aligned 4 of 29 (withheld), partial 18.8% and drift 28.0%, with the
ordering unknown for the same reason. Receipt gatecal_34e099cfe78b.
Two cautions belong to the method, not to this corpus. The gate is replayed on the commit as it landed, so a warning that made its author change the diff left no trace: a check that works is graded on the changes it failed to stop. And the convergence request is the commit subject, written after the change.
A second corpus (2026-10-10)¶
The same command, on the released 4.4.0 engine, was pointed at bashbop-api:
2,340 non-merge commits, 618 replayed, and none the gate or the convergence
score could not evaluate. That is more than five times this repository's
corpus.
| Verdict | n | repaired | 95% interval | lift |
|---|---|---|---|---|
| PASS | 272 | 32.0% | 26.7% to 37.7% | 0.74x |
| WARN | 343 | 52.2% | 46.9% to 57.4% | 1.20x |
| FAIL | 3 | withheld | — | — |
The intervals do not overlap. On this corpus a change the gate warned on was repaired more often than one it passed. The lift is modest because the base rate is high, 43.4% (268 of 618), and lift compresses toward 1.0 as the base rate rises, as it did in the flag tables above.
The alarm is common, and wrong nearly half the time. The gate raised an alarm on 56.0% of changes (52.0% to 59.9%). Of those 346 alarms, 165 were on a change nothing later repaired: 47.7% (42.5% to 52.9%). It had raised an alarm on 181 of the 268 changes that were repaired: 67.5% (61.7% to 72.9%).
One check carries the result. Risk review warned on 333 of the 346
alarmed changes, repaired 52.3% (46.9% to 57.6%), a lift of 1.21x. Migration
safety warned on 29 (18 repaired), Release discipline on 15 (8) and Secret
safety on 1, all under the minimum sample and withheld. What this corpus
grades is the risk-path rule. It says nothing about the other checks in either
direction.
The convergence band orders outcomes and does not separate them.
| Band | n | repaired | 95% interval | lift |
|---|---|---|---|---|
| aligned | 82 | 32.9% | 23.7% to 43.7% | 0.76x |
| partial | 172 | 44.2% | 37.0% to 51.7% | 1.02x |
| drift | 364 | 45.3% | 40.3% to 50.5% | 1.04x |
Aligned is repaired least and drift most, so the ordering holds, but the drift and aligned intervals overlap, and partial and drift are a point apart. 364 of the 618 commits, 58.9%, score as drift against their own subject, which says more about a commit subject as a stand-in for the request than about the changes.
Across the two corpora the direction is the same, PASS repaired less often
than WARN, and it is established on one. None of it shows that the gate
prevents a repair. The replay ran on an otherwise idle machine, which matters:
the repair join reads a git call that times out as no evidence, so a loaded
machine can undercount repairs without saying so. Receipt
gatecal_0059db10d1e2.
The trial¶
SOLUMBE_CHECK_MODE=trial puts each change in one of two arms, by a hash of
the repository root and the commit the change is being built on. In the shown
arm convergence_score and the local review_gate answer as usual. In the
withheld arm the MCP server computes and records the same result and tells the
agent only that it was recorded. SOLUMBE_CHECK_SHOWN_SHARE (default 0.5) sets
the split, and decisions go to ~/.solumbe/check-decisions.jsonl
(SOLUMBE_CHECK_LOG).
A blocking FAIL is shown in both arms: a secret in a diff is not withheld for a measurement. The command line, the pre-commit hook, CI and the pull request gate are never part of the trial, which also means an agent in the withheld arm can reach the result another way. Both facts pull the arms together, so the trial understates whatever effect there is.
solumbe calibrate <repo> --trial grades the arms on the first commit made on
each head, joined to repaired. node scripts/hooks/check-outcomes.mjs grades
them sooner, on the same-session proxies the route outcomes use: whether the
next prompt pushed back, and whether the next turn edited the same files.
Grading the request read (2026-10-18)¶
Everything above grades solumbe's own signals. The request read is not
solumbe's: context --online asks a model what kind of work a request is and
which candidate files it needs, and relabels the intent when the answer clears
CHOICE_FLOOR (0.5). Until now it had a provider, Jev, and no measurement.
It now has two providers. Jev answers typed System One questions with
probabilities trained against outcomes. Claude answers through one forced tool
call (src/lib/claude-read.js) whose input schema is the answer: intent and
capability are enums over the same labels, each with a stated confidence,
and relevance scores every candidate file by name. A reply that fails
validation goes back as an is_error tool result, once; whatever survives is
mapped into Jev's answer shape, so interpretRead judges both the same way.
SOLUMBE_READ_PROVIDER picks one; otherwise a TypeSafe key keeps Jev and an
Anthropic key alone selects Claude.
Both are graded by solumbe eval --reads on the reads suite of
evals/corpus.json: 24 requests over 12 committed fixtures, each labelled with
its intent, the tool that answers it and the files it needs. Four of them are
question-shaped, check X against Y, labelled review or explain, because
solumbe's action words cannot read them at all.
| solumbe alone | Jev (jev-latest) |
Claude (claude-haiku-5-5) |
|
|---|---|---|---|
| Intent accuracy, the read's own choice | 13 / 24 | 23 / 24 | not run |
Cleared CHOICE_FLOOR |
n/a | 20 / 24 | not run |
| Accuracy when it cleared | n/a | 20 / 20 | not run |
| Intent a pack would carry | 13 / 24 | 21 / 24 | not run |
Read as unknown |
9 | 3 | not run |
| Brier score of the stated confidence | n/a | 0.05 | not run |
| Capability accuracy | n/a | 11 / 24 | not run |
| Expected files demoted (under 0.2) | n/a | 0 of 27 | not run |
| Other candidates demoted | n/a | 10 of 46 | not run |
| Cost for 24 reads, mean latency | 0 | $0.0014, 214 ms | not run |
solumbe's own action words are mapped onto the read's labels first (create is
add, update is change, rename is refactor), so the baseline is not
marked wrong for vocabulary.
The read is worth having, and the floor is where it loses. Jev chose the
right intent 23 times in 24, and every answer at or above 0.9 (19 of them) was
right. The four under the floor were right three times. Two of those were
question-shaped: check the order routes against the order repository read as
review at 0.43, is the refund flow consistent with the stripe webhook? as
explain at 0.39; the floor discarded both and the pack kept unknown. (The
third, the checkout button crashes on click as debug at 0.44, already
matched solumbe's own word.) The one wrong answer, check the stripe webhook
against the checkout service as debug, came at 0.23. Under the floor Jev was
right 75% of the time at a mean confidence of 0.37: underconfident, if
anything, and exactly where question-shaped requests land.
Capability is the weak question. Jev named the tool the label expected 11
times in 24, at a median confidence under 0.4, and it is not applied anywhere.
For edit requests it prefers repo_search and repo_map where the labels say
context_pack; that is as much a question about the labels as about the read.
Relevance does no harm here. No file a case needs was scored under 0.2, and 10 of 46 other candidates were, which is the demotion the read exists for.
The Claude column was not run then. The provider, its schema, retry and mapping were tested against a mocked API; the key on the measuring machine was rejected (401). It was first run on 2026-11-09, on the suite as it stood then; see the next section.
Two cautions belong to the method. Jev's answers move by up to 0.05 between
runs (docs/18), so a case near the floor can cross it; this is one run. And
Claude's confidence is the model's own statement, not a trained probability,
so its Brier score and bands are the number to read first: an accurate read
whose confidences are not calibrated makes CHOICE_FLOOR a guess.
The Claude read, and reasoning first (2026-11-09)¶
Adding let's think step by step to the read's prompt would change nothing: a
forced tool call leaves no room for text before it, and forced tool_choice
cannot be combined with extended thinking. The room has to be inside the
answer. So the read's tool schema can open with a reasoning string, which
strict tool use writes before intent; it is never applied, and the prompt and
every other field stay the same, so the two runs differ in one thing.
Both were run twice on the reads suite, by then 29 requests, with
claude-haiku-5-5, alternating the variants; Jev (jev-1.14.0) was run once
on the same suite for comparison.
| Claude, answers only | Claude, reasoning first | Jev | |
|---|---|---|---|
| Intent accuracy, the read's own choice | 28, 28 / 29 | 29, 28 / 29 | 29 / 29 |
Cleared CHOICE_FLOOR |
29, 29 | 29, 29 | 27 |
| Intent a pack would carry | 28, 28 | 29, 28 | 27 |
| Brier score of the stated confidence | 0.061, 0.059 | 0.051, 0.061 | 0.054 |
| Capability accuracy | 24, 23 / 29 | 27, 27 / 29 | 15 / 29 |
| Expected files demoted (under 0.2) | 0 of 33 | 0 of 33 | 0 of 33 |
| Other candidates demoted | 15, 14 of 62 | 22, 20 of 62 | 20 of 62 |
| Cost for 29 reads | $0.0093 | $0.0121 | $0.0017 |
| Mean latency | 2.5 s, 1.8 s | 3.9 s, 2.7 s | 160 ms |
Intent does not move. Reasoning fixed why does the checkout crash? in
both runs (debug where answers-only said explain) and lost how do I add a
refund route? once (explain at 0.6, against the label add). One case is
3.4 points here; that is noise.
The other two answers do. Reasoning first named the expected tool 27 times in 29 in both runs, against 24 and 23, and it demoted 22 and 20 of 62 candidates the work does not need, against 15 and 14, while still demoting none of the 33 it does. Relevance is applied (a demoted file leaves the pack); capability is not yet. The price is 11% more tokens, a third more cost and about a second more per read.
So the Claude read now reasons first by default; --no-reasoning, or
SOLUMBE_CLAUDE_READ_REASONING=0 outside the eval, turns it off. Jev stays the
default provider: it chose every intent right and demoted as many candidates as
reasoning-first Claude, at a seventh of the cost and under a tenth of the
latency. Two of its intents fell under the floor, and its capability answer is
the weakest of the three. Two
runs per variant is a small sample; rerun both before reading anything into a
one-case difference.
ANTHROPIC_API_KEY=... solumbe eval --reads --provider claude --out claude-reads.md
ANTHROPIC_API_KEY=... solumbe eval --reads --provider claude --no-reasoning --out claude-reads-answers-only.md
What changes because of it¶
- Weights stop being folklore. Changing one becomes a reviewed code change justified by a measurement, not a preference.
- Policy profiles get an honest basis.
high-riskcan require the flags that demonstrably predict trouble in that repository. - The claim upgrades. "Deterministic" becomes "deterministic and measured" and unlike a benchmark, it is measured on the user's own history, which no competitor can copy.
Why not simply call a calibrated model?¶
Because the dependency buys an opinion where solumbe sells evidence. A vendor's probabilities are calibrated against its training outcomes, not against this repository's. Adding a hosted call also trades the product's clearest sentence, local-first, model-agnostic, no model calls in the core path, for a qualified version of it.
If the backtest later exposes a blind spot that path rules genuinely cannot close, that is the moment to revisit, with a measured job for the signal to do. The boundary contract for that day, covering ratchet-only escalation, an allowlisted payload and a receipt over the questions and answers, is written and parked on a branch rather than merged, so the decision stays explicit instead of incremental.
What this is NOT¶
Not a bug predictor. Not a model, and not a route to one. Not automatic weight tuning: a measured weight is still a human-reviewed code change. Not a claim that git history is ground truth; it is a set of named proxies, each with known failure modes. And not a new reason to block a merge: calibration grades the signal, it does not become one.
Sources¶
- TypeSafe AI, Introducing System One Models & Jev: https://typesafe.ai/blog/introducing-system-one-models-and-jev
- TypeSafe AI, System One concepts and calibrated decisions: https://docs.typesafe.ai/concepts/system-one
- TypeSafe AI, How to build with System One (confidence thresholds, atomic questions): https://docs.typesafe.ai/concepts/how-to-build-with-system-one
- solumbe source referenced above:
src/lib/pr-review.js,src/lib/risk-paths.js,src/lib/converge.js,src/lib/policy.js - Companions: Deterministic Verification, Deterministic Verification, Deterministic Verification, Evaluation Guide