@@ -4,8 +4,8 @@ import { resolveModelFamilyPolicy } from "./model-family-policy.js";
44describe ( "resolveModelFamilyPolicy" , ( ) => {
55 test ( "defaults are permissive for an unrecognized provider" , ( ) => {
66 const policy = resolveModelFamilyPolicy ( {
7- providerName : "openai " ,
8- model : "gpt-4.1 " ,
7+ providerName : "unknown-provider " ,
8+ model : "unknown-model " ,
99 } ) ;
1010 expect ( policy . family ) . toBe ( "default" ) ;
1111 expect ( policy . applyGrokFinishBias ) . toBe ( false ) ;
@@ -55,8 +55,8 @@ describe("resolveModelFamilyPolicy", () => {
5555
5656 test ( "advertisedToolDeny is empty by default and never contains use_skill" , ( ) => {
5757 const leaf = resolveModelFamilyPolicy ( {
58- providerName : "openai " ,
59- model : "gpt-4.1 " ,
58+ providerName : "unknown-provider " ,
59+ model : "unknown-model " ,
6060 orchestrator : false ,
6161 } ) ;
6262 expect ( leaf . advertisedToolDeny ) . toEqual ( [ ] ) ;
@@ -124,12 +124,12 @@ describe("resolveModelFamilyPolicy", () => {
124124 orchestrator : true ,
125125 } ) ;
126126 expect ( orchestrator . promptResidual ) . toBeUndefined ( ) ;
127- // Default-family probe: anthropic/claude-sonnet-4 would hit the claude
128- // row now, and the gpt row has NOT landed yet (#1135), so openai/gpt-4.1
129- // is the probe that still resolves to the default family.
127+ // Default-family probe: anthropic/claude-sonnet-4 hits the claude row
128+ // and openai/gpt-4.1 hits the gpt row (#1135), so an unrecognized
129+ // provider is the probe that still resolves to the default family.
130130 const base = resolveModelFamilyPolicy ( {
131- providerName : "openai " ,
132- model : "gpt-4.1 " ,
131+ providerName : "unknown-provider " ,
132+ model : "unknown-model " ,
133133 } ) ;
134134 expect ( base . family ) . toBe ( "default" ) ;
135135 expect ( base . promptResidual ) . toBeUndefined ( ) ;
@@ -154,21 +154,22 @@ describe("resolveModelFamilyPolicy", () => {
154154 expect ( orchestrator . promptResidual ) . toBeUndefined ( ) ;
155155 } ) ;
156156
157- // The gpt family row has NOT landed yet (#1135): openai/gpt-4.1 and
158- // codex/gpt-5.1 are default-family probes here, asserting they resolve to
159- // the default family with no residual . Grok keeps its CL-8297 tool-budget
157+ // The gpt family row has landed (#1135): openai/gpt-4.1 and codex/gpt-5.1
158+ // resolve to the gpt family with the narrate-before-tools residual, leaf
159+ // and orchestrator alike ( no carve-out) . Grok keeps its CL-8297 tool-budget
160160 // residual — the "no residual" claim below is default-family-only.
161- test ( "gpt probes resolve to default with no residual; grok keeps its tool budget" , ( ) => {
161+ test ( "gpt probes resolve to gpt with the narrate residual; grok keeps its tool budget" , ( ) => {
162162 for ( const input of [
163163 { providerName : "openai" , model : "gpt-4.1" } ,
164164 { providerName : "codex" , model : "gpt-5.1" } ,
165165 ] as const ) {
166- const policy = resolveModelFamilyPolicy ( {
167- ...input ,
168- orchestrator : false ,
169- } ) ;
170- expect ( policy . family ) . toBe ( "default" ) ;
171- expect ( policy . promptResidual ) . toBeUndefined ( ) ;
166+ for ( const orchestrator of [ false , true ] ) {
167+ const policy = resolveModelFamilyPolicy ( { ...input , orchestrator } ) ;
168+ expect ( policy . family ) . toBe ( "gpt" ) ;
169+ expect ( policy . promptResidual ) . toContain (
170+ "Narrate before tools (GPT worker):" ,
171+ ) ;
172+ }
172173 }
173174 const grok = resolveModelFamilyPolicy ( {
174175 providerName : "xai/default" ,
@@ -178,4 +179,24 @@ describe("resolveModelFamilyPolicy", () => {
178179 expect ( grok . family ) . toBe ( "grok" ) ;
179180 expect ( grok . promptResidual ) . toContain ( "Tool budget:" ) ;
180181 } ) ;
182+ test ( "gpt resolves its own family on permissive default thresholds (CL-8310)" , ( ) => {
183+ const gpt = resolveModelFamilyPolicy ( {
184+ providerName : "codex/default" ,
185+ model : "gpt-5.5" ,
186+ } ) ;
187+ const base = resolveModelFamilyPolicy ( {
188+ providerName : "anthropic" ,
189+ model : "claude-sonnet-4" ,
190+ } ) ;
191+ expect ( gpt . family ) . toBe ( "gpt" ) ;
192+ // No eval characterization for gpt tool-only stretches yet: ship the
193+ // permissive default, no finish-bias, no discipline rules. The
194+ // narrate-before-tools residual is prompt-level (see prompts.ts), not a
195+ // threshold.
196+ expect ( gpt . toolOnlyTurnNudgeAt ) . toBe ( base . toolOnlyTurnNudgeAt ) ;
197+ expect ( gpt . subAgentStallTimeoutMs ) . toBe ( base . subAgentStallTimeoutMs ) ;
198+ expect ( gpt . applyGrokFinishBias ) . toBe ( false ) ;
199+ expect ( gpt . toolDisciplineRules ) . toBeUndefined ( ) ;
200+ expect ( gpt . advertisedToolDeny ) . toEqual ( [ ] ) ;
201+ } ) ;
181202} ) ;
0 commit comments