Record why model_ref narrowing shipped without an API version - #778
Merged
Conversation
The Brain change made model_ref nullable on AgentResponse, and it had been required and non-null. A field that was always present becoming sometimes absent breaks a caller that dereferenced it without checking, which the type said it never had to do. So the stance says version it, and it shipped unversioned. That was the right call for reasons that are not obvious from the diff, which is exactly when they need writing down. Two of the three reasons are durable: the withdrawn guarantee was a guarantee to return a sentinel (provider `deterministic`, model `agent:<Name>:v1`) for every rule-brained agent, so the field stopped misreporting rather than becoming less informative, and `brain` was added alongside as a strictly better replacement. The third reason is that there are no consumers, and it is doing most of the work while being the one that expires. It is written with its expiry attached: once the REST surface has any consumer outside this repository, the precedent stops applying. Without that, the next narrowing change cites this section for "CORA does not version" and the sentinel argument quietly becomes a general licence. Also states what the openapi.json snapshot does and does not buy. Drift is caught, so every contract change is visible in a diff; classifying one as additive or breaking is still a judgement, which is why the reasoning belongs in prose next to it rather than in the diff alone. Counted rather than quoted while writing this: eighteen of TWENTY-FOUR seed definitions are rule-brained, and the model-brained six are two agent roles times three deployment profiles. The design memo said "twenty, eighteen Rule, two LanguageModel", which does not add up; the memo is corrected too. Docs build clean under --strict. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Item 4 of the brain-arc follow-ups. Docs only, no code.
What the decision is
The Brain change made
model_refnullable onAgentResponse. It had been required and non-null:A field that was always present becoming sometimes absent breaks a caller that dereferenced it without checking, which the type said it never had to do. Under the additive-default stance that is breaking, and it shipped with no
X-Cora-Api-Versionheader. That was the right call, for reasons not visible in the diff.Two are durable. The withdrawn guarantee was a guarantee to return a sentinel: a rule-brained agent had no model to name, so the field carried provider
deterministic, modelagent:<Name>:v1. A caller readingmodel_ref.providergot a provider naming no vendor and a model never called or approved. Andbrainwas added alongside as a strictly better replacement.The third is that there are no consumers, and it does most of the work while being the one that expires. It is written with the expiry attached: once the REST surface has any consumer outside this repository, this precedent stops applying. Without that sentence the next narrowing change cites this section for "CORA does not version," and a narrow sentinel argument quietly becomes a general licence.
Also recorded
What the
openapi.jsonsnapshot buys.test_openapi_driftcatches drift, so every contract change is visible in a diff; whether a given diff is additive or breaking is still a judgement. That is why the reasoning belongs in prose next to the snapshot rather than in the diff alone.A count corrected while writing it
I counted rather than quoting the design memo, and the memo was wrong.
AgentSeedIdentity(...)constructions insrc/cora: 24, of which 18 are rule-brained and 6 name a model. The memo said "twenty seeded agents, eighteen Rule, two LanguageModel", which does not add up. The six are two agent roles (RunDebriefer, CautionDrafter) across three deployment profiles each. The doc states it as seed definitions and says so explicitly, since roles and definitions differ by a factor of three on that side.Docs build clean under
--strict; 37,425 architecture tests passing.🤖 Generated with Claude Code