11// SPDX-License-Identifier: MIT
2- use serde:: Deserialize ;
2+ use serde:: { Deserialize , Serialize } ;
33
44#[ derive( Debug , Clone , Copy , PartialEq , Eq , Deserialize ) ]
55#[ serde( rename_all = "lowercase" ) ]
@@ -18,6 +18,111 @@ impl ExportFormat {
1818 }
1919}
2020
21+ #[ derive( Debug , Clone , Copy , Default , PartialEq , Eq , Deserialize , Serialize ) ]
22+ #[ serde( rename_all = "lowercase" ) ]
23+ pub enum RetentionClass {
24+ Durable ,
25+ #[ default]
26+ Operational ,
27+ Audit ,
28+ Ephemeral ,
29+ }
30+
31+ impl RetentionClass {
32+ pub fn as_str ( self ) -> & ' static str {
33+ match self {
34+ Self :: Durable => "durable" ,
35+ Self :: Operational => "operational" ,
36+ Self :: Audit => "audit" ,
37+ Self :: Ephemeral => "ephemeral" ,
38+ }
39+ }
40+
41+ pub fn parse ( input : & str ) -> Option < Self > {
42+ match input. trim ( ) . to_ascii_lowercase ( ) . as_str ( ) {
43+ "durable" => Some ( Self :: Durable ) ,
44+ "operational" => Some ( Self :: Operational ) ,
45+ "audit" => Some ( Self :: Audit ) ,
46+ "ephemeral" => Some ( Self :: Ephemeral ) ,
47+ _ => None ,
48+ }
49+ }
50+
51+ pub fn default_ttl_seconds ( self ) -> Option < i64 > {
52+ match self {
53+ Self :: Durable => None ,
54+ Self :: Operational => Some ( 90 * 24 * 60 * 60 ) ,
55+ Self :: Audit => Some ( 365 * 24 * 60 * 60 ) ,
56+ Self :: Ephemeral => Some ( 14 * 24 * 60 * 60 ) ,
57+ }
58+ }
59+
60+ pub fn from_entry_type ( entry_type : & str ) -> Option < Self > {
61+ match entry_type. trim ( ) . to_ascii_lowercase ( ) . as_str ( ) {
62+ "decision" | "policy" | "rule" | "convention" | "contract" | "procedure"
63+ | "playbook" | "runbook" => Some ( Self :: Durable ) ,
64+ "trace" | "security" | "rollback" | "permission" | "audit" => Some ( Self :: Audit ) ,
65+ "chatter" | "scratch" | "transient" | "temporary" | "ephemeral" => {
66+ Some ( Self :: Ephemeral )
67+ }
68+ "observation" | "note" | "finding" | "fact" | "memory" | "focus_summary" => {
69+ Some ( Self :: Operational )
70+ }
71+ _ => None ,
72+ }
73+ }
74+
75+ pub fn classify (
76+ explicit : Option < Self > ,
77+ entry_type : & str ,
78+ text : & str ,
79+ context : Option < & str > ,
80+ ) -> Self {
81+ if let Some ( explicit) = explicit {
82+ return explicit;
83+ }
84+ if let Some ( mapped) = Self :: from_entry_type ( entry_type) {
85+ return mapped;
86+ }
87+
88+ let combined = match context {
89+ Some ( context) if !context. trim ( ) . is_empty ( ) => {
90+ format ! ( "{} {}" , text. trim( ) , context. trim( ) ) . to_ascii_lowercase ( )
91+ }
92+ _ => text. trim ( ) . to_ascii_lowercase ( ) ,
93+ } ;
94+ if [
95+ "architectural" ,
96+ "architecture" ,
97+ "convention" ,
98+ "always" ,
99+ "never" ,
100+ "api contract" ,
101+ "must " ,
102+ "do not" ,
103+ ]
104+ . iter ( )
105+ . any ( |needle| combined. contains ( needle) )
106+ {
107+ return Self :: Durable ;
108+ }
109+ if [ "rollback" , "permission" , "security event" , "audit" ]
110+ . iter ( )
111+ . any ( |needle| combined. contains ( needle) )
112+ {
113+ return Self :: Audit ;
114+ }
115+ if [ "throwaway" , "temporary" , "transient" , "scratch" ]
116+ . iter ( )
117+ . any ( |needle| combined. contains ( needle) )
118+ {
119+ return Self :: Ephemeral ;
120+ }
121+
122+ Self :: Operational
123+ }
124+ }
125+
21126#[ derive( Debug , Clone , Default , Deserialize ) ]
22127pub struct StoreRequest {
23128 pub decision : Option < String > ,
@@ -29,6 +134,7 @@ pub struct StoreRequest {
29134 pub confidence : Option < f64 > ,
30135 pub reasoning_depth : Option < String > ,
31136 pub ttl_seconds : Option < i64 > ,
137+ pub retention_class : Option < RetentionClass > ,
32138}
33139
34140#[ derive( Debug , Clone , Deserialize ) ]
@@ -54,6 +160,7 @@ pub struct ImportMemory {
54160 pub observed_at : Option < String > ,
55161 pub valid_from : Option < String > ,
56162 pub valid_until : Option < String > ,
163+ pub retention_class : Option < RetentionClass > ,
57164}
58165
59166#[ derive( Debug , Clone , Deserialize ) ]
@@ -72,6 +179,7 @@ pub struct ImportDecision {
72179 pub observed_at : Option < String > ,
73180 pub valid_from : Option < String > ,
74181 pub valid_until : Option < String > ,
182+ pub retention_class : Option < RetentionClass > ,
75183}
76184
77185#[ derive( Debug , Clone ) ]
0 commit comments