@@ -382,6 +382,14 @@ export interface ResolveEffortForRoleOpts {
382382 roleDefault ?: ReasoningEffort ;
383383 /** Parent session effort — used only when the role default is not supported. */
384384 parentEffort ?: ReasoningEffort ;
385+ /**
386+ * True when the parent effort was operator-chosen (explicit) rather than a
387+ * resolved/derived value. An explicit parent effort is a fleet-wide pin that
388+ * outranks the role default; the unset case keeps CL-5162 (leaf medium /
389+ * orchestrator high). Kept as a real separate marker — do NOT infer this from
390+ * `parentEffort` truthiness.
391+ */
392+ parentExplicit ?: boolean ;
385393 model : string ;
386394 isCodex ?: boolean ;
387395 providerEfforts ?: readonly ReasoningEffort [ ] ;
@@ -393,10 +401,12 @@ export interface ResolveEffortForRoleOpts {
393401 *
394402 * Precedence (first match wins):
395403 * 1. Explicit pin (clamped onto supported when the pin is not in the set)
396- * 2. Role default when present in `supported`
397- * 3. Parent effort when present in `supported`
398- * 4. Clamp of role default onto `supported`
399- * 5. undefined when `supported` is empty
404+ * 2. Explicit parent effort (operator-chosen fleet pin) when present in
405+ * `supported` — clamped onto the set when not (CL-10227)
406+ * 3. Role default when present in `supported`
407+ * 4. Parent effort when present in `supported`
408+ * 5. Clamp of role default onto `supported`
409+ * 6. undefined when `supported` is empty
400410 *
401411 * Pins are still highest precedence, but an unsupported pin is clamped so the
402412 * pure API owns the "never emit an unsupported effort" invariant (callers that
@@ -406,6 +416,7 @@ export function pickEffortFromCascade(opts: {
406416 pin ?: ReasoningEffort ;
407417 roleDefault : ReasoningEffort ;
408418 parentEffort ?: ReasoningEffort ;
419+ parentExplicit ?: boolean ;
409420 supported : readonly ReasoningEffort [ ] ;
410421} ) : ReasoningEffort | undefined {
411422 if ( opts . supported . length === 0 ) return undefined ;
@@ -414,6 +425,13 @@ export function pickEffortFromCascade(opts: {
414425 ? opts . pin
415426 : clampEffort ( opts . pin , opts . supported ) ;
416427 }
428+ // An explicit (operator-chosen) parent effort is a fleet-wide pin: it beats
429+ // the role default so a primary cycled to none really gives none workers.
430+ if ( opts . parentExplicit === true && opts . parentEffort !== undefined ) {
431+ return opts . supported . includes ( opts . parentEffort )
432+ ? opts . parentEffort
433+ : clampEffort ( opts . parentEffort , opts . supported ) ;
434+ }
417435 if ( opts . supported . includes ( opts . roleDefault ) ) return opts . roleDefault ;
418436 if (
419437 opts . parentEffort !== undefined &&
@@ -427,10 +445,13 @@ export function pickEffortFromCascade(opts: {
427445/**
428446 * Resolve reasoning effort for a sub-agent spawn.
429447 *
430- * Why parent is below role default: a /agent high selection on the primary must
431- * not force every leaf onto high — that multiplies the sol+high latency cliff
432- * across the fleet. Parent still fills gaps when the role default is not in the
433- * model's supported set but the parent effort is.
448+ * Precedence: explicit pin > explicit parent (operator-chosen fleet pin) > role
449+ * default > derived parent > clamp. An explicit primary effort — including
450+ * `none`/off — is fleet-wide, so it beats both the leaf (medium) and the
451+ * orchestrator (high) role default. The unset parent case keeps CL-5162: the
452+ * role default outranks a derived parent so a /agent high selection on the
453+ * primary does not force every leaf onto high (which would multiply the
454+ * sol+high latency cliff across the fleet).
434455 */
435456export function resolveEffortForRole (
436457 opts : ResolveEffortForRoleOpts ,
@@ -452,6 +473,7 @@ export function resolveEffortForRole(
452473 ...( opts . parentEffort !== undefined
453474 ? { parentEffort : opts . parentEffort }
454475 : { } ) ,
476+ ...( opts . parentExplicit === true ? { parentExplicit : true } : { } ) ,
455477 supported,
456478 } ) ;
457479}
0 commit comments