@@ -321,9 +321,25 @@ def remember(
321321"""
322322 target_path = self .config .vault_path / relative
323323 previous_content = (
324- target_path .read_text (encoding = "utf-8" ) if target_path .exists () else None
324+ target_path .read_text (encoding = "utf-8" )
325+ if memory_kind != "adaptive" and target_path .exists ()
326+ else None
325327 )
326- path = self ._write (relative , content )
328+ adaptive_previous_content : str | None = None
329+ path = target_path if memory_kind == "adaptive" else self ._write (relative , content )
330+
331+ def publish_adaptive () -> None :
332+ nonlocal adaptive_previous_content
333+ adaptive_previous_content = (
334+ path .read_text (encoding = "utf-8" ) if path .exists () else None
335+ )
336+ self ._write (relative , content )
337+
338+ def rollback_adaptive_publish () -> None :
339+ if adaptive_previous_content is None :
340+ path .unlink (missing_ok = True )
341+ else :
342+ atomic_write_text (path , adaptive_previous_content )
327343
328344 def restore_failed_write () -> None :
329345 current = self .store .document (document_id )
@@ -350,9 +366,15 @@ def restore_failed_write() -> None:
350366 ** (registration_metadata or {}),
351367 },
352368 relations = relations ,
369+ insert_only = memory_kind == "adaptive" ,
370+ publish = publish_adaptive if memory_kind == "adaptive" else None ,
371+ rollback_publish = (
372+ rollback_adaptive_publish if memory_kind == "adaptive" else None
373+ ),
353374 )
354375 except Exception :
355- restore_failed_write ()
376+ if memory_kind != "adaptive" :
377+ restore_failed_write ()
356378 raise
357379 if not registered :
358380 restore_failed_write ()
@@ -391,13 +413,31 @@ def promote_adaptive(
391413 )
392414 title = f"Retained context: { title_line [:100 ]} "
393415 promoted_at = datetime .now (UTC ).isoformat (timespec = "milliseconds" )
416+ promotion_score = float (usage .get ("promotion_score" , 0.0 ))
417+ promotion_score_threshold = float (
418+ usage .get ("promotion_score_threshold" , 0.0 )
419+ )
420+ raw_components = usage .get ("promotion_score_components" , {})
421+ score_components = (
422+ {str (key ): float (value ) for key , value in raw_components .items ()}
423+ if isinstance (raw_components , Mapping )
424+ else {}
425+ )
426+ component_lines = "" .join (
427+ f" - { name .replace ('_' , ' ' ).title ()} : { value :.3f} \n "
428+ for name , value in score_components .items ()
429+ )
394430 body = (
395431 bounded
396432 + "\n \n ## Automatic retention evidence\n \n "
397433 + f"- Distinct sessions: { int (usage .get ('distinct_sessions' , 0 ))} \n "
434+ + f"- Distinct providers: { int (usage .get ('distinct_providers' , 0 ))} \n "
398435 + f"- Distinct days: { int (usage .get ('distinct_days' , 0 ))} \n "
399436 + f"- Search sessions: { int (usage .get ('search_sessions' , 0 ))} \n "
400437 + f"- Context injections: { int (usage .get ('context_injections' , 0 ))} \n "
438+ + f"- Promotion score: { promotion_score :.3f} / "
439+ + f"{ promotion_score_threshold :.3f} \n "
440+ + ("- Score components:\n " + component_lines if component_lines else "" )
401441 + f"- Source document: `{ source_document_id } `\n "
402442 )
403443 created_id , path = self .remember (
@@ -418,8 +458,12 @@ def promote_adaptive(
418458 "adaptive_source_document_id" : source_document_id ,
419459 "promoted_at" : promoted_at ,
420460 "last_used_at" : str (usage .get ("last_used_at" ) or promoted_at ),
461+ "promotion_score" : promotion_score ,
462+ "promotion_score_threshold" : promotion_score_threshold ,
463+ "promotion_score_components" : score_components ,
421464 "promotion_reason" : {
422465 "distinct_sessions" : int (usage .get ("distinct_sessions" , 0 )),
466+ "distinct_providers" : int (usage .get ("distinct_providers" , 0 )),
423467 "distinct_days" : int (usage .get ("distinct_days" , 0 )),
424468 "search_sessions" : int (usage .get ("search_sessions" , 0 )),
425469 "context_injections" : int (
0 commit comments