@@ -372,6 +372,26 @@ impl BulletinRefreshOutcome {
372372}
373373
374374const CORTEX_ONE_SHOT_MAX_TURNS : usize = 1 ;
375+ const CORTEX_INTRADAY_SYNTHESIS_SYSTEM_FALLBACK : & str = "You write concise working-memory summaries for the cortex.\n \n Output one narrative summary paragraph and nothing else." ;
376+ const CORTEX_DAILY_SUMMARY_SYSTEM_FALLBACK : & str = "You write daily activity summaries for the cortex.\n \n Output the daily activity summary and nothing else." ;
377+
378+ fn render_static_prompt_or_fallback (
379+ prompt_engine : & crate :: prompts:: engine:: PromptEngine ,
380+ template_name : & ' static str ,
381+ fallback : & ' static str ,
382+ ) -> String {
383+ match prompt_engine. render_static ( template_name) {
384+ Ok ( prompt) => prompt,
385+ Err ( error) => {
386+ tracing:: warn!(
387+ %error,
388+ template_name,
389+ "failed to render static cortex prompt, using fallback"
390+ ) ;
391+ fallback. to_string ( )
392+ }
393+ }
394+ }
375395
376396fn maybe_spawn_synthesis_task (
377397 task : & mut Option < tokio:: task:: JoinHandle < anyhow:: Result < bool > > > ,
@@ -3255,13 +3275,11 @@ pub async fn maybe_synthesize_intraday_batch(
32553275
32563276 // Render the synthesis prompt.
32573277 let prompt_engine = deps. runtime_config . prompts . load ( ) ;
3258- let synthesis_preamble = match prompt_engine. render_static ( "cortex_intraday_synthesis_system" ) {
3259- Ok ( prompt) => prompt,
3260- Err ( error) => {
3261- tracing:: warn!( %error, "failed to render cortex_intraday_synthesis_system prompt" ) ;
3262- return Err ( error. into ( ) ) ;
3263- }
3264- } ;
3278+ let synthesis_preamble = render_static_prompt_or_fallback (
3279+ & prompt_engine,
3280+ "cortex_intraday_synthesis_system" ,
3281+ CORTEX_INTRADAY_SYNTHESIS_SYSTEM_FALLBACK ,
3282+ ) ;
32653283 let prompt = prompt_engine. render_intraday_synthesis (
32663284 unsynthesized. len ( ) ,
32673285 & time_start_str,
@@ -3419,13 +3437,11 @@ pub async fn maybe_synthesize_daily_summary(
34193437
34203438 let wm_config = * * deps. runtime_config . working_memory . load ( ) ;
34213439 let prompt_engine = deps. runtime_config . prompts . load ( ) ;
3422- let synthesis_preamble = match prompt_engine. render_static ( "cortex_daily_summary_system" ) {
3423- Ok ( prompt) => prompt,
3424- Err ( error) => {
3425- tracing:: warn!( %error, "failed to render cortex_daily_summary_system prompt" ) ;
3426- return Err ( error. into ( ) ) ;
3427- }
3428- } ;
3440+ let synthesis_preamble = render_static_prompt_or_fallback (
3441+ & prompt_engine,
3442+ "cortex_daily_summary_system" ,
3443+ CORTEX_DAILY_SUMMARY_SYSTEM_FALLBACK ,
3444+ ) ;
34293445 let prompt = prompt_engine. render_daily_summary (
34303446 & yesterday,
34313447 wm_config. daily_summary_max_words ,
@@ -4646,22 +4662,24 @@ async fn fetch_memories_for_association(
46464662mod tests {
46474663 use super :: {
46484664 BULLETIN_REFRESH_CIRCUIT_OPEN_SECS , BULLETIN_REFRESH_CIRCUIT_OPEN_THRESHOLD , BranchTracker ,
4649- BulletinRefreshOutcome , CortexReceiverOutcome , GatheredSections , HealthRuntimeState ,
4650- MAINTENANCE_TASK_CANCEL_GRACE_SECS , MaintenanceTimeoutAction , ReceiverClosedBehavior ,
4651- Signal , SynthesisTaskBackoff , WorkerTracker , apply_cancelled_warmup_status,
4652- build_kill_targets, claim_detached_completion, collect_synthesis_task,
4653- detached_timeout_transition, generate_if_dirty_under_lock, handle_cortex_receiver_result,
4654- has_completed_initial_warmup, is_cancelled_control_result, is_terminal_control_result,
4655- maintenance_task_timeout, maintenance_timeout_action,
4656- mark_knowledge_synthesis_version_complete, maybe_close_bulletin_refresh_circuit,
4657- maybe_generate_bulletin_under_lock, maybe_spawn_synthesis_task,
4658- parse_structured_success_flag, push_signal_into_buffer, record_bulletin_refresh_failure,
4659- should_execute_warmup, should_generate_bulletin_from_bulletin_loop, signal_from_event,
4660- summarize_signal_text, take_lagged_control_flag,
4665+ BulletinRefreshOutcome , CORTEX_INTRADAY_SYNTHESIS_SYSTEM_FALLBACK , CortexReceiverOutcome ,
4666+ GatheredSections , HealthRuntimeState , MAINTENANCE_TASK_CANCEL_GRACE_SECS ,
4667+ MaintenanceTimeoutAction , ReceiverClosedBehavior , Signal , SynthesisTaskBackoff ,
4668+ WorkerTracker , apply_cancelled_warmup_status, build_kill_targets,
4669+ claim_detached_completion, collect_synthesis_task, detached_timeout_transition,
4670+ generate_if_dirty_under_lock, handle_cortex_receiver_result, has_completed_initial_warmup,
4671+ is_cancelled_control_result, is_terminal_control_result, maintenance_task_timeout,
4672+ maintenance_timeout_action, mark_knowledge_synthesis_version_complete,
4673+ maybe_close_bulletin_refresh_circuit, maybe_generate_bulletin_under_lock,
4674+ maybe_spawn_synthesis_task, parse_structured_success_flag, push_signal_into_buffer,
4675+ record_bulletin_refresh_failure, render_static_prompt_or_fallback, should_execute_warmup,
4676+ should_generate_bulletin_from_bulletin_loop, signal_from_event, summarize_signal_text,
4677+ take_lagged_control_flag,
46614678 } ;
46624679 use crate :: ProcessEvent ;
46634680 use crate :: agent:: process_control:: ControlActionResult ;
46644681 use crate :: memory:: MemoryType ;
4682+ use crate :: prompts:: engine:: PromptEngine ;
46654683 use crate :: tasks:: TaskStatus ;
46664684 use crate :: tasks:: TaskStore ;
46674685 use futures:: FutureExt ;
@@ -4692,6 +4710,19 @@ mod tests {
46924710 assert ! ( should_execute_warmup( warmup_config, true ) ) ;
46934711 }
46944712
4713+ #[ test]
4714+ fn static_cortex_prompt_fallback_keeps_synthesis_running_when_template_fails ( ) {
4715+ let prompt_engine = PromptEngine :: new ( "en" ) . expect ( "prompt engine should build" ) ;
4716+
4717+ let prompt = render_static_prompt_or_fallback (
4718+ & prompt_engine,
4719+ "missing_cortex_synthesis_template" ,
4720+ CORTEX_INTRADAY_SYNTHESIS_SYSTEM_FALLBACK ,
4721+ ) ;
4722+
4723+ assert_eq ! ( prompt, CORTEX_INTRADAY_SYNTHESIS_SYSTEM_FALLBACK ) ;
4724+ }
4725+
46954726 #[ test]
46964727 fn run_warmup_once_semantics_enabled_runs_without_force ( ) {
46974728 let warmup_config = crate :: config:: WarmupConfig {
0 commit comments