+
    <j7                       a  R% t0 t R t^ RIt^ RIHt ^ RIHtHtHt ^ RI	t	^ RI
HtHtHt ^RIHt  ! R R]4      t ! R R	]4      t ! R
 R]4      t ! R R]4      t ! R R]4      t ! R R]4      t ! R R]4      t ! R R]4      t ! R R]4      t ! R R]4      tR]R]R]R]R]R]R ]R!]R"]/	t] ^ k R# R$ lt. R&OtR# )'uF  Canonical config loader with schema validation.

Every config file is loaded via `validate_and_load(path, schema_name)`.
Unknown / typo'd / wrong-typed / missing-required fields raise
SchemaValidationError at load time, NOT at first use.

Per Tenet 6 (architectural-law.md:186-263) — fail-loud is the default.

Adding a new config file:
    1. Define a Pydantic model in this file.
    2. Register it in SCHEMAS.
    3. Call validate_and_load(path, schema_name) from the loader.

NOTE: this file deliberately does NOT use `from __future__ import
annotations`. Pydantic v2 needs annotations resolvable at class-definition
time to build its validators, and when the module is loaded via importlib
proxy (pipeline/lib/config_schema.py), the deferred-string-annotation form
breaks `model_validate` with "class is not fully defined" errors.
N)Path)AnyOptionalType)	BaseModel
ConfigDictValidationError)SchemaValidationErrorc                   0    ] tR t^tRt]! RRRR7      tRtR# )_BaseConfigSchemazBase for every Recoil config schema.

Default: extra='forbid' so typos at the top level fail loud.
Subclasses with extension fields (model_profiles entries, etc.) override.
forbidFT)extrafrozenvalidate_assignment N)__name__
__module____qualname____firstlineno____doc__r   model_config__static_attributes__r       ڏ/Users/joeturnerlin/Code/recoil-sessions/Joes-MacBook-Pro/adhoc--claude--atlas-redesign--20260625T050330Z-1fd50d09/recoil/core/config_schema.pyr   r      s    
  Lr   r   c                      a  ] tR t^/t o RtRtRtRtRtRt	Rt
RtRtRtRtRtRtRtRtRtRtRtRtRtRtRtRtRtRt]! RR7      tV 3R ltRt V t!R# )PipelineConfigSchemazCSchema for config/pipeline_config.json (170-line top-level config).Nallowr   c                v  < V ^8  d   Qh/ S[ ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R	&   S[S[,          ;R
&   S[S[,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[ ,          ;R&   S[S[ ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   # )   schema_versionprojects_rootvisual_state_namespacerecoil_engine_rootoutput_rootdefault_modelexploration_modelfallback_exploration_modeldefault_image_sizeproduction_aspect_ratiogrid_aspect_ratiostoryboard_iterationmax_references_per_shotmax_concurrent_api_callsvisual_defaultscomplexity_tiersvideoroutingmodel_capabilitiescoverage_strategycritic_flagsenable_scene_visual_locksenable_moodboard_to_textlocation_ref_modepreviz_temperature)intr   strdictr   boolfloat)format__classdict__s   "r   __annotate__!PipelineConfigSchema.__annotate__/   s       C='  %SM0  !,  #%  C='   }+  !)4 " !,# $ &c]1% &  }+' ( #4S>29) * &c]1+ , 'sm2- 2 d38n-43 4 tCH~.55 6 DcN#*7 8 d38n%,9 : !c3h07; <  S#X/6= > 4T	?+2? D  (~4E F 'tn3G H  }+I J !.K r   r   )"r   r   r   r   r   r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r   r   __annotate_func__r   __classdictcell__r?   s   @r   r   r   /   s     M
 $(M,0(,!%K $(M'+04 )--1'+59-1.2 15O15&*E(,G3726.2L 15/3'+*. G,LQ  r   r   c                   B   a  ] tR t^]t o Rt]! RR7      tV 3R ltRtV t	R# )ModelProfilesSchemau   Schema for config/model_profiles.json.

Top-level keys are model_ids → entry dicts. Entries vary widely between
image and video models, so values are kept as `dict[str, Any]` and only
the `schema_version` field is typed at the root.
r   r   c                &   < V ^8  d   Qh/ S[ ;R&   # r   r    r9   )r>   r?   s   "r   r@    ModelProfilesSchema.__annotate__]   s       r   r   N
r   r   r   r   r   r   r   rB   r   rC   rD   s   @r   rF   rF   ]   s      G,L  r   rF   c                   B   a  ] tR t^mt o Rt]! RR7      tV 3R ltRtV t	R# )ProviderStrategySchemazSchema for config/provider_strategy.json.

Top-level: schema_version + one entry per model_id with shape:
    {
        "capability_exceptions": dict,
        "primary": str,
        "primary_tier": str,
    }
r   r   c                &   < V ^8  d   Qh/ S[ ;R&   # rH   rI   )r>   r?   s   "r   r@   #ProviderStrategySchema.__annotate__m   s       r   r   NrK   rD   s   @r   rM   rM   m   s      G,L  r   rM   c                   J   a  ] tR t^t o RtRtRt]! RR7      tV 3R lt	Rt
V tR# )PricingRatesSchemazzSchema for config/pricing_rates.json.

Top-level: schema_version, note, and rate_cards (list of date-stamped
rate cards).
Nr   r   c                   < V ^8  d   Qh/ S[ ;R&   S[S[,          ;R&   S[S[S[S[S[3,          ,          ,          ;R&   # )r   r    note
rate_cards)r9   r   r:   listr;   r   )r>   r?   s   "r   r@   PricingRatesSchema.__annotate__   sB        3-  d38n-.5 r   r   )r   r   r   r   r   rS   rT   r   r   rB   r   rC   rD   s   @r   rQ   rQ      s'      D15JG,L  r   rQ   c                   V   a  ] tR t^t o RtRtRtRtRtRt	]
! RR7      tV 3R ltRtV tR# )ModelRolesSchemau   Schema for config/model_roles.json.

Top-level: role-buckets (image/video/text/tts/qc), each a mapping of
role_name → model_id. Plus a `_doc` documentation string preserved via
extra='allow' (Pydantic v2 ignores _-prefixed field declarations).
Nr   r   c                   < V ^8  d   Qh/ S[ ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   # )r   r    imager0   textttsqc)r9   r   r;   r:   )r>   r?   s   "r   r@   ModelRolesSchema.__annotate__   s        DcN#*  DcN#*  4S>
")  
$sCx.	!(  	c3h ' r   r   )r   r   r   r   r   rZ   r0   r[   r\   r]   r   r   rB   r   rC   rD   s   @r   rX   rX      s6      '+E&*E%)D$(C#'BG,L  r   rX   c                   R   a  ] tR t^t o RtRtRtRtRt]	! RR7      t
V 3R ltRtV tR# )PromptConstantsSchemau  Schema for config/prompt_constants.json.

Top-level sections: production, casting, shared, formatter_limits.
Each section is a flat string→string (or string→limits-dict for
formatter_limits) map. Plus a `_doc` documentation string preserved
via extra='allow'.
Nr   r   c                  < V ^8  d   Qh/ S[ ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[S[S[3,          3,          ,          ;R&   # )r   r    
productioncastingsharedformatter_limitsr9   r   r;   r:   r   )r>   r?   s   "r   r@   "PromptConstantsSchema.__annotate__   s        c3h(/  d38n%,  T#s(^$+  tCc3h$789@ r   r   )r   r   r   r   r   rb   rc   rd   re   r   r   rB   r   rC   rD   s   @r   r`   r`      s2      ,0J(,G'+F<@G,L  r   r`   c                   R   a  ] tR t^t o RtRtRtRtRt]	! RR7      t
V 3R ltRtV tR# )LexiconSchemaa  Schema for config/lexicon.json.

Top-level: kinetic_map (list of {id, pattern, descriptor}), fallback
(str), lighting_direction_map and lighting_quality_map (lists of
{pattern, direction|quality}). Plus a `_doc` documentation string
preserved via extra='allow'.
Nr   r   c                  < V ^8  d   Qh/ S[ ;R&   S[S[S[S[S[3,          ,          ,          ;R&   S[S[,          ;R&   S[S[S[S[S[3,          ,          ,          ;R&   S[S[S[S[S[3,          ,          ,          ;R&   # )r   r    kinetic_mapfallbacklighting_direction_maplighting_quality_map)r9   r   rU   r;   r:   r   )r>   r?   s   "r   r@   LexiconSchema.__annotate__   s        $tCH~./6  sm"  %T$sCx.%9:A  #4S#X#78? r   r   )r   r   r   r   r   rk   rl   rm   rn   r   r   rB   r   rC   rD   s   @r   ri   ri      s3      37K"H=A;?G,L  r   ri   c                   V   a  ] tR t^t o RtRtRtRtRtRt	]
! RR7      tV 3R ltRtV tR# )RefDescriptorsSchemaa#  Schema for config/ref_descriptors.json.

Top-level keys are ref-class names (character, location, wardrobe,
hair_makeup, props), each mapping to a per-class descriptor block.
Descriptor blocks vary by class (composite_grid vs parallel_singles
strategies) so values stay as `dict[str, Any]`.
Nr   r   c                   < V ^8  d   Qh/ S[ ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   S[S[S[S[3,          ,          ;R&   # )r   r    	characterlocationwardrobehair_makeuppropsrf   )r>   r?   s   "r   r@   !RefDescriptorsSchema.__annotate__   s        S#X'.  tCH~&-  tCH~&-  $sCx.)0  DcN#* r   r   )r   r   r   r   r   rs   rt   ru   rv   rw   r   r   rB   r   rC   rD   s   @r   rq   rq      s6      +/I)-H)-H,0K&*EG,L!  r   rq   c                   B   a  ] tR t^t o Rt]! RR7      tV 3R ltRtV t	R# )PromptBibleSchemau  Schema for config/PROMPT_BIBLE.yaml.

Top-level keys are model_ids (seedream-v4.5, kling-v3, veo-3.1, ...) →
per-model rule dicts (meta, prompt, refs, aspect_ratio, first_last_frame,
duration, audio, gotchas). Per-model dicts vary widely so values stay as
`dict[str, Any]`.
r   r   c                &   < V ^8  d   Qh/ S[ ;R&   # rH   rI   )r>   r?   s   "r   r@   PromptBibleSchema.__annotate__   s       r   r   NrK   rD   s   @r   rz   rz      s      G,L  r   rz   pipeline_configmodel_profilesprovider_strategypricing_ratesmodel_rolesprompt_constantslexiconref_descriptorsprompt_biblec                ^    V ^8  d   QhR\         R\        R\        \        \        3,          /# )r   pathschema_namereturn)r   r:   r;   r   )r>   s   "r   r@   r@     s)     ./ ./D ./s ./tCH~ ./r   c           	        V\         9  d.   \        RV: R\        \         P                  4       4       24      hV P	                  4       '       g   \        RV  24      h V P                  R9   d(   \        P                  ! V P                  RR7      4      pM'\        P                  ! V P                  RR7      4      p \         V,          p VP                  V4      pTP!                  RR7      #   \        P                  \        P                  3 d   p\        RT  RT 24      ThRp?ii ; i  \         d   p\        RT  R	T: R
T 24      ThRp?ii ; i)a  Load a config file and validate against the registered schema.

Args:
    path: Path to the config file (.json or .yaml).
    schema_name: Key in SCHEMAS dict.

Returns:
    Validated config as a dict (model.model_dump()).

Raises:
    SchemaValidationError: on shape mismatch, missing required field,
        wrong type, unknown extra field (where extra='forbid'), unknown
        schema_name, or parse failure.
    FileNotFoundError: if path does not exist.
zUnknown schema_name z. Registered: zConfig file not found: zutf-8)encodingzConfig file z failed to parse: Nz	 (schema z) failed validation:
T)exclude_none)z.yamlz.yml)SCHEMASr	   sortedkeysis_fileFileNotFoundErrorsuffixyaml	safe_load	read_textjsonloadsJSONDecodeError	YAMLErrormodel_validater   
model_dump)r   r   rawe
schema_clsmodels   &&    r   validate_and_loadr     sU     '!#";/ 2!',,.124
 	
 <<>>"9$ @AA;;++..!ABC**T^^W^=>C %J))#. ..#   $..1 #4& 21#6
	  #4&	+8Nc
 	s6   7C. &C. D- .%D*D%%D*-E8EEc                x    V ^8  d   Qh/ ^ \         9   d&   \        \        \        \        ,          3,          ;R&   # )r   r   )__conditional_annotations__r;   r:   r   r   )r>   s   "r   r@   r@      s4      l
 
c4)**	+ 
mr   )r   r	   r   r   rF   rM   rQ   rX   r`   ri   rq   rz   )r   r   r   pathlibr   typingr   r   r   r   pydanticr   r   r   
exceptionsr	   r   r   rF   rM   rQ   rX   r`   ri   rq   rz   r   r   __all__r@   )r   s   @r   <module>r      s   (   & &  ; ; -
	 
 (-, (-\
-+ 
- -. -&-* -"-( -*-- -*-% -*-, -,-) -$ +)/'#-}+%
/ 
./br   