Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions drift-proposals/openai-gpt-6.1-terra-new-family.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# New / unclassified model family: gpt-6.1-terra

Provider: openai
Detected: 2026-10-26
Status: RESOLVED — decision recorded below and applied to the registry

This model family appeared in a live /models listing but matches no classification rule (include, exclude, -preview, gemma). drift-sync never silently classifies a new family.

## Decision
<!-- drift-sync never auto-classifies a new family. A HUMAN decides, by
changing the line below to either:

Decision: include — aimock mocks this family on the chat surface
Decision: exclude — wrong modality / retired / preview; not ours

The NEXT drift-sync run then applies the mechanical registry edit to
includeFamilies or excludeFamilies respectively, and re-pins that
set's membership checksum in the same commit (still zero-LLM: this
is a human-authored decision, not generated code).

ONE EXCEPTION, and it is the common one for `exclude`: a VOICE/AUDIO
family (realtime / audio / live / transcribe / whisper / voice / tts)
is watched by a SECOND canary whose seed set — knownVoiceModelFamilies
in src/__tests__/drift/voice-models.ts — is a deliberately disjoint
surface drift-sync does not write. Classifying such a family in the
registry alone leaves that canary red, so the run would gate-fail and
revert, nightly, forever. drift-sync therefore does NOT auto-apply it:
it drops a `-voice-seed-set.md` note and a human makes both edits in
one reviewed commit. -->
Decision: INCLUDE (applied 2026-10-26 — includeFamilies.openai in
`src/__tests__/drift/model-registry.ts`, with the `includeFamilies.openai`
re-pin in `src/__tests__/drift/logic-pin.test.ts`, plus the static OpenAI
/models wave in `src/__tests__/drift/models.drift.ts`).

Rationale: gpt-6.1 point release of the included `gpt-5.6-terra` line and
sibling of the included `gpt-6.1-sol`. The normalizer keeps the `.1` version
token, so it is its own family and must be enumerated.

Evidence (live, 2026-10-26): `GET /v1/models/gpt-6.1-terra` returned 200 with
`id`, `object`, `created: 1791908780`, `owned_by: "system"`,
`shutdown_date: null` — no capability field, the same shape as `gpt-6.1-sol`.
A minimal `POST /v1/chat/completions` with `model: "gpt-6.1-terra"` returned
200, `object: "chat.completion"`, `finish_reason: "stop"`, and a real assistant
text turn. It is text chat on the surface aimock mocks. Not a voice/audio
family, so no `knownVoiceModelFamilies` edit is needed.
2 changes: 1 addition & 1 deletion src/__tests__/drift/logic-pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ describe("classification-logic checksum freeze (Phase-0 anti-silence guard)", ()
const DATA_FROZEN: Record<string, { members: () => string[]; pin: string }> = {
"includeFamilies.openai": {
members: () => [...includeFamilies.openai].sort(),
pin: "7c28e670d7ce3a5903b47aa605f3af391ba816529eaefbb4f81ac4f60c30ec0a",
pin: "d62f65955c9b867171e8889381bb818c724a3b5f9c3a60fcdf51716f82ee05ca",
},
"includeFamilies.anthropic": {
members: () => [...includeFamilies.anthropic].sort(),
Expand Down
17 changes: 17 additions & 0 deletions src/__tests__/drift/model-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,23 @@ export const includeFamilies: Record<Provider, Set<string>> = {
// Decision: INCLUDE, recorded in
// drift-proposals/openai-gpt-6.1-sol-new-family.md.
"gpt-6.1-sol",
// gpt-6.1 point release of the included `gpt-5.6-terra` line, sibling of
// `gpt-6.1-sol` above. First listed by drift run 40422235776 (2026-10-26;
// `created: 1791908780`). The normalizer keeps the `.1` version token, so
// it is its own family and must be enumerated.
//
// Classified on a LIVE PROBE (2026-10-26), not on lineage alone.
// `GET /v1/models/gpt-6.1-terra` returns only `id` / `object` / `created` /
// `owned_by: "system"` / `shutdown_date: null`, the same shape as
// `gpt-6.1-sol`. A minimal /v1/chat/completions call returned 200,
// `object: "chat.completion"`, `finish_reason: "stop"` and a real assistant
// text turn, the same shape `gpt-6.1-sol` returned. No name token places it
// in an excluded cluster, and it is not a voice/audio family, so no
// knownVoiceModelFamilies pairing.
//
// Decision: INCLUDE, recorded in
// drift-proposals/openai-gpt-6.1-terra-new-family.md.
"gpt-6.1-terra",
// Codex line (coding chat; text output)
"gpt-5-codex",
"gpt-5.1-codex",
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/drift/models.drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,8 @@ describe("recorded /models family waves are classified", () => {
// gpt-6.1 point release (2026-09-24..30 wave, first listed 09-30; its own
// normalized family)
"gpt-6.1-sol",
// gpt-6.1-terra (2026-10-26 wave, drift run 40422235776; probe-verified text chat)
"gpt-6.1-terra",
// o-series reasoning
"o1",
"o1-pro",
Expand Down
26 changes: 25 additions & 1 deletion src/__tests__/drift/text-drift.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import { describe, it, expect } from "vitest";

import { isClassifiedFamily, excludeFamilies } from "./model-registry.js";
import { isClassifiedFamily, excludeFamilies, includeFamilies } from "./model-registry.js";
import { normalizeModelFamily } from "./model-family.js";
import { unclassifiedFamilies } from "./text-drift.js";

Expand Down Expand Up @@ -562,3 +562,27 @@ describe("the 2026-10-14..18 model-family waves are classified", () => {
]);
});
});

// ---------------------------------------------------------------------------
// The 2026-10-26 wave — BEHAVIOURAL coverage of `gpt-6.1-terra` (INCLUDE), in
// the same shape as the blocks above. Evidence sits beside the entry in
// model-registry.ts and in drift-proposals/.
// ---------------------------------------------------------------------------

describe("the 2026-10-26 model-family wave is classified", () => {
it("gpt-6.1-terra is INCLUDED in a /models-shaped payload", () => {
expect(includeFamilies.openai.has("gpt-6.1-terra")).toBe(true);
expect(isClassifiedFamily("gpt-6.1-terra", "openai")).toBe(true);
expect(excludeFamilies.openai.has("gpt-6.1-terra")).toBe(false);
expect(unclassifiedFamilies(["gpt-6.1-sol", "gpt-6.1-terra"], "openai")).toEqual([]);
});

it("the new key does not classify a neighbouring family", () => {
// NEGATIVE CONTROLS: without these, `toEqual([])` above is also what a
// neutered `unclassifiedFamilies` would produce.
expect(normalizeModelFamily("gpt-6.1-terra", "openai")).toBe("gpt-6.1-terra");
expect(unclassifiedFamilies(["gpt-6.1-luna"], "openai")).toEqual(["gpt-6.1-luna"]);
expect(unclassifiedFamilies(["gpt-6.2-terra"], "openai")).toEqual(["gpt-6.2-terra"]);
expect(unclassifiedFamilies(["gpt-6.1-terra-tts"], "openai")).toEqual(["gpt-6.1-terra-tts"]);
});
});
Loading