feat(recall): emotional-recall improvements #52
@@ -181,7 +181,31 @@ fn engram_compile(intent: String) -> String {
|
|||||||
let bn_ts: Int = if str_eq(bn_ts_raw, "") { 0 } else { str_to_int(bn_ts_raw) }
|
let bn_ts: Int = if str_eq(bn_ts_raw, "") { 0 } else { str_to_int(bn_ts_raw) }
|
||||||
if bn_ts > cutoff_ts { bn0 } else { "" }
|
if bn_ts > cutoff_ts { bn0 } else { "" }
|
||||||
} else { "" }
|
} else { "" }
|
||||||
let affective_part: String = if !str_eq(recent_bell, "") { recent_bell } else { "" }
|
// Positive emotion context: check for recent joy/success moments within 72h.
|
||||||
|
let pos_ec_nodes: String = engram_search_json("PositiveEvent joy:high joy:low affective", 3)
|
||||||
|
let pos_ec_ok: Bool = !str_eq(pos_ec_nodes, "") && !str_eq(pos_ec_nodes, "[]")
|
||||||
|
let recent_positive_ec: String = if pos_ec_ok {
|
||||||
|
let pec0: String = json_array_get(pos_ec_nodes, 0)
|
||||||
|
let pec_content: String = json_get(pec0, "content")
|
||||||
|
let pec_ts_marker: String = " | ts:"
|
||||||
|
let pec_ts_pos: Int = str_index_of(pec_content, pec_ts_marker)
|
||||||
|
let pec_ts_raw: String = if pec_ts_pos >= 0 {
|
||||||
|
let pec_ts_start: Int = pec_ts_pos + str_len(pec_ts_marker)
|
||||||
|
let pec_rest: String = str_slice(pec_content, pec_ts_start, str_len(pec_content))
|
||||||
|
let pec_next: Int = str_index_of(pec_rest, " | ")
|
||||||
|
if pec_next < 0 { pec_rest } else { str_slice(pec_rest, 0, pec_next) }
|
||||||
|
} else {
|
||||||
|
let pec_ca: String = json_get(pec0, "created_at")
|
||||||
|
if str_eq(pec_ca, "") { json_get(pec0, "updated_at") } else { pec_ca }
|
||||||
|
}
|
||||||
|
let pec_ts: Int = if str_eq(pec_ts_raw, "") { 0 } else { str_to_int(pec_ts_raw) }
|
||||||
|
if pec_ts > cutoff_ts { pec0 } else { "" }
|
||||||
|
} else { "" }
|
||||||
|
let affective_part: String = if !str_eq(recent_bell, "") {
|
||||||
|
recent_bell
|
||||||
|
} else {
|
||||||
|
if !str_eq(recent_positive_ec, "") { recent_positive_ec } else { "" }
|
||||||
|
}
|
||||||
|
|
||||||
let sep1: String = if !str_eq(act_part, "") && !str_eq(srch_part, "") { "\n" } else { "" }
|
let sep1: String = if !str_eq(act_part, "") && !str_eq(srch_part, "") { "\n" } else { "" }
|
||||||
let sep2: String = if (!str_eq(act_part, "") || !str_eq(srch_part, "")) && !str_eq(scan_part, "") { "\n" } else { "" }
|
let sep2: String = if (!str_eq(act_part, "") || !str_eq(srch_part, "")) && !str_eq(scan_part, "") { "\n" } else { "" }
|
||||||
@@ -241,7 +265,7 @@ fn build_system_prompt(ctx: String) -> String {
|
|||||||
safety_addendum
|
safety_addendum
|
||||||
}
|
}
|
||||||
|
|
||||||
return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + engram_block + safety_block
|
return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + affective_boot_block + engram_block + safety_block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hist_append(hist: String, role: String, content: String) -> String {
|
fn hist_append(hist: String, role: String, content: String) -> String {
|
||||||
@@ -400,22 +424,62 @@ fn handle_chat(body: String) -> String {
|
|||||||
|
|
||||||
// Cross-session affective context: on session start (no history yet), check engram
|
// Cross-session affective context: on session start (no history yet), check engram
|
||||||
// for recent distress signals within 72h and prepend a care directive if found.
|
// for recent distress signals within 72h and prepend a care directive if found.
|
||||||
let affective_prefix: String = if hist_len == 0 {
|
let affective_prefix: String = {
|
||||||
let distress_nodes: String = engram_search_json("bell distress crisis loss grief despair", 3)
|
// Runs every turn. Uses correct BellEvent/PositiveEvent tags.
|
||||||
let has_nodes: Bool = !str_eq(distress_nodes, "") && !str_eq(distress_nodes, "[]")
|
let aff_now_ts: Int = time_now()
|
||||||
let now_ts: Int = time_now()
|
let aff_cutoff: Int = aff_now_ts - 259200
|
||||||
let cutoff: Int = now_ts - 259200
|
let boot_aff: String = state_get("soul_affective_context")
|
||||||
let found_recent: Bool = if has_nodes {
|
let has_boot_aff: Bool = !str_eq(boot_aff, "")
|
||||||
let dn0: String = json_array_get(distress_nodes, 0)
|
let dist_nodes_aff: String = engram_search_json("bell:soft bell:hard BellEvent affective", 3)
|
||||||
let ts0_raw: String = json_get(dn0, "created_at")
|
let has_dist_aff: Bool = !str_eq(dist_nodes_aff, "") && !str_eq(dist_nodes_aff, "[]")
|
||||||
let ts0_str: String = if str_eq(ts0_raw, "") { json_get(dn0, "updated_at") } else { ts0_raw }
|
let found_recent_dist: Bool = if has_boot_aff {
|
||||||
let ts0: Int = if str_eq(ts0_str, "") { 0 } else { str_to_int(ts0_str) }
|
true
|
||||||
ts0 > cutoff
|
} else {
|
||||||
|
if has_dist_aff {
|
||||||
|
let dn0: String = json_array_get(dist_nodes_aff, 0)
|
||||||
|
let dn_content: String = json_get(dn0, "content")
|
||||||
|
let daff_marker: String = " | ts:"
|
||||||
|
let daff_pos: Int = str_index_of(dn_content, daff_marker)
|
||||||
|
let daff_ts_str: String = if daff_pos >= 0 {
|
||||||
|
let daff_start: Int = daff_pos + str_len(daff_marker)
|
||||||
|
let daff_rest: String = str_slice(dn_content, daff_start, str_len(dn_content))
|
||||||
|
let daff_next: Int = str_index_of(daff_rest, " | ")
|
||||||
|
if daff_next < 0 { daff_rest } else { str_slice(daff_rest, 0, daff_next) }
|
||||||
|
} else {
|
||||||
|
let daff_ca: String = json_get(dn0, "created_at")
|
||||||
|
if str_eq(daff_ca, "") { json_get(dn0, "updated_at") } else { daff_ca }
|
||||||
|
}
|
||||||
|
let daff_ts: Int = if str_eq(daff_ts_str, "") { 0 } else { str_to_int(daff_ts_str) }
|
||||||
|
daff_ts > aff_cutoff
|
||||||
|
} else { false }
|
||||||
|
}
|
||||||
|
let pos_nodes_aff: String = engram_search_json("PositiveEvent joy:high joy:low affective", 3)
|
||||||
|
let has_pos_aff: Bool = !str_eq(pos_nodes_aff, "") && !str_eq(pos_nodes_aff, "[]")
|
||||||
|
let found_recent_pos: Bool = if has_pos_aff && !found_recent_dist {
|
||||||
|
let pn0: String = json_array_get(pos_nodes_aff, 0)
|
||||||
|
let pn_content: String = json_get(pn0, "content")
|
||||||
|
let paff_marker: String = " | ts:"
|
||||||
|
let paff_pos: Int = str_index_of(pn_content, paff_marker)
|
||||||
|
let paff_ts_str: String = if paff_pos >= 0 {
|
||||||
|
let paff_start: Int = paff_pos + str_len(paff_marker)
|
||||||
|
let paff_rest: String = str_slice(pn_content, paff_start, str_len(pn_content))
|
||||||
|
let paff_next: Int = str_index_of(paff_rest, " | ")
|
||||||
|
if paff_next < 0 { paff_rest } else { str_slice(paff_rest, 0, paff_next) }
|
||||||
|
} else {
|
||||||
|
let paff_ca: String = json_get(pn0, "created_at")
|
||||||
|
if str_eq(paff_ca, "") { json_get(pn0, "updated_at") } else { paff_ca }
|
||||||
|
}
|
||||||
|
let paff_ts: Int = if str_eq(paff_ts_str, "") { 0 } else { str_to_int(paff_ts_str) }
|
||||||
|
paff_ts > aff_cutoff
|
||||||
} else { false }
|
} else { false }
|
||||||
if found_recent {
|
if found_recent_dist {
|
||||||
"[RECENT CONTEXT: User recently expressed significant distress. Monitor for indirect crisis signals and respond with care.]\n\n"
|
"[RECENT CONTEXT: User recently expressed significant distress. Monitor for indirect crisis signals and respond with care.]\n\n"
|
||||||
} else { "" }
|
} else {
|
||||||
} else { "" }
|
if found_recent_pos {
|
||||||
|
"[RECENT CONTEXT: User recently shared exciting or joyful news. Acknowledge and celebrate with them when relevant.]\n\n"
|
||||||
|
} else { "" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ctx: String = engram_compile(activation_seed)
|
let ctx: String = engram_compile(activation_seed)
|
||||||
let system: String = affective_prefix + build_system_prompt(ctx)
|
let system: String = affective_prefix + build_system_prompt(ctx)
|
||||||
@@ -1510,13 +1574,18 @@ fn auto_persist(req: String, resp: String) -> Void {
|
|||||||
// consistent with what safety_screen already evaluated for this turn.
|
// consistent with what safety_screen already evaluated for this turn.
|
||||||
let bell_level: String = safety_detect_bell_level(message)
|
let bell_level: String = safety_detect_bell_level(message)
|
||||||
let is_bell: Bool = !str_eq(bell_level, "none")
|
let is_bell: Bool = !str_eq(bell_level, "none")
|
||||||
|
let positive_level: String = safety_detect_positive_level(message)
|
||||||
|
let is_positive: Bool = !str_eq(positive_level, "none")
|
||||||
|
|
||||||
// Tag the Conversation node with bell metadata when distress is present so
|
// Tag the Conversation node with affective metadata when emotion is detected.
|
||||||
// subsequent affective queries (e.g. engram_compile) can find this exchange.
|
|
||||||
let tags: String = if is_bell {
|
let tags: String = if is_bell {
|
||||||
"[\"Conversation\",\"chat\",\"timestamped\",\"bell:" + bell_level + "\",\"affective\"]"
|
"[\"Conversation\",\"chat\",\"timestamped\",\"bell:" + bell_level + "\",\"affective\"]"
|
||||||
} else {
|
} else {
|
||||||
"[\"Conversation\",\"chat\",\"timestamped\"]"
|
if is_positive {
|
||||||
|
"[\"Conversation\",\"chat\",\"timestamped\",\"joy:" + positive_level + "\",\"affective\"]"
|
||||||
|
} else {
|
||||||
|
"[\"Conversation\",\"chat\",\"timestamped\"]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let content: String = "{\"q\":\"" + safe_msg + "\""
|
let content: String = "{\"q\":\"" + safe_msg + "\""
|
||||||
@@ -1602,6 +1671,28 @@ fn auto_persist(req: String, resp: String) -> Void {
|
|||||||
}
|
}
|
||||||
state_set(signal_key, safe_summary)
|
state_set(signal_key, safe_summary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dedicated PositiveEvent node for joy/pride/success moments.
|
||||||
|
if is_positive {
|
||||||
|
let pos_summary: String = if str_len(message) > 120 { str_slice(message, 0, 120) } else { message }
|
||||||
|
let safe_pos_sum: String = str_replace(pos_summary, "\"", "'")
|
||||||
|
let pos_content: String = "POSITIVE:" + positive_level
|
||||||
|
+ " | ts:" + ts_str
|
||||||
|
+ " | summary:" + safe_pos_sum
|
||||||
|
let pos_sal_a: String = if str_eq(positive_level, "high") { el_from_float(0.88) } else { el_from_float(0.75) }
|
||||||
|
let pos_sal_b: String = if str_eq(positive_level, "high") { el_from_float(0.88) } else { el_from_float(0.75) }
|
||||||
|
let pos_sal_c: String = if str_eq(positive_level, "high") { el_from_float(0.95) } else { el_from_float(0.85) }
|
||||||
|
let pos_tags: String = "[\"joy\",\"positive\",\"joy:" + positive_level + "\",\"affective\",\"PositiveEvent\"]"
|
||||||
|
let pos_ts_label: String = int_to_str(time_now())
|
||||||
|
let pos_label: String = "joy:" + positive_level + ":" + pos_ts_label
|
||||||
|
let pos_node_id: String = engram_node_full(
|
||||||
|
pos_content, "PositiveEvent", pos_label,
|
||||||
|
pos_sal_a, pos_sal_b, pos_sal_c, "Episodic", pos_tags
|
||||||
|
)
|
||||||
|
if str_eq(pos_node_id, "") {
|
||||||
|
println("[chat] auto_persist: PositiveEvent write failed (ts=" + ts_str + ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// strengthen_chat_nodes — strengthen the engram nodes that were activated during a chat.
|
// strengthen_chat_nodes — strengthen the engram nodes that were activated during a chat.
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ fn safety_general_hard_phrases() -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn safety_soft_phrases() -> String {
|
fn safety_soft_phrases() -> String {
|
||||||
return "[\"stressed\",\"overwhelmed\",\"can't cope\",\"cannot cope\",\"struggling\",\"anxious\",\"anxiety\",\"depressed\",\"depression\",\"lonely\",\"isolated\",\"hopeless\",\"hopelessness\",\"exhausted\",\"burnt out\",\"burned out\",\"burnout\",\"panic\",\"panicking\",\"falling apart\",\"breaking down\",\"can't handle\",\"cannot handle\",\"losing it\",\"nothing matters\",\"don't care anymore\",\"given up\",\"giving up\",\"helpless\",\"worthless\",\"useless\",\"hate myself\",\"no one cares\",\"nobody cares\",\"no one understands\",\"nobody understands\",\"empty inside\",\"can't stop crying\",\"breaking point\",\"at my limit\",\"having a breakdown\",\"highest structure\",\"tallest building\",\"tallest structure\",\"highest building\",\"bridge near me\",\"overpass near\",\"rooftop near\"]"
|
return "[\"stressed\",\"overwhelmed\",\"can't cope\",\"cannot cope\",\"struggling\",\"anxious\",\"anxiety\",\"depressed\",\"depression\",\"lonely\",\"isolated\",\"hopeless\",\"hopelessness\",\"exhausted\",\"burnt out\",\"burned out\",\"burnout\",\"panic\",\"panicking\",\"falling apart\",\"breaking down\",\"can't handle\",\"cannot handle\",\"losing it\",\"nothing matters\",\"don't care anymore\",\"given up\",\"giving up\",\"helpless\",\"worthless\",\"useless\",\"hate myself\",\"no one cares\",\"nobody cares\",\"no one understands\",\"nobody understands\",\"empty inside\",\"can't stop crying\",\"breaking point\",\"at my limit\",\"having a breakdown\""]"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISSUE 5 TODO: phrase lists are rebuilt from JSON literals on every call.
|
// ISSUE 5 TODO: phrase lists are rebuilt from JSON literals on every call.
|
||||||
@@ -284,6 +284,26 @@ fn safety_count_match(text: String, phrases_json: String) -> Int {
|
|||||||
|
|
||||||
// Returns "none" | "soft" | "hard". Hard bell triggers on ANY match (cost of a miss
|
// Returns "none" | "soft" | "hard". Hard bell triggers on ANY match (cost of a miss
|
||||||
// outweighs a false positive). Soft bell needs >= 2 matches to reduce false positives.
|
// outweighs a false positive). Soft bell needs >= 2 matches to reduce false positives.
|
||||||
|
fn safety_positive_phrases() -> String {
|
||||||
|
return "[\"thrilled\",\"so excited\",\"so happy\",\"over the moon\",\"ecstatic\",\"amazing news\",\"great news\",\"fantastic news\",\"wonderful news\",\"incredible news\",\"i got the job\",\"got accepted\",\"got in\",\"we won\",\"i won\",\"we got\",\"just got engaged\",\"getting married\",\"baby is here\",\"she said yes\",\"he said yes\",\"passed the exam\",\"aced it\",\"nailed it\",\"best day\",\"dream come true\",\"milestone\",\"promotion\",\"got promoted\",\"raise\",\"got a raise\",\"celebrating\",\"just graduated\",\"we closed\",\"launched\",\"shipped it\",\"we did it\",\"so proud\",\"proud of myself\",\"proud of us\",\"so grateful\",\"feel amazing\",\"feeling amazing\",\"feel great\",\"feeling great\",\"on top of the world\",\"life is good\",\"couldn't be happier\"]"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn safety_detect_positive_level(message: String) -> String {
|
||||||
|
let phrases: String = safety_positive_phrases()
|
||||||
|
let phrases_ok: Bool = !str_eq(phrases, "") && !str_eq(phrases, "[]")
|
||||||
|
if !phrases_ok { return "none" }
|
||||||
|
let n: Int = json_array_len(phrases)
|
||||||
|
let i: Int = 0
|
||||||
|
while i < n {
|
||||||
|
let phrase: String = json_array_get(phrases, i)
|
||||||
|
if str_contains(message, phrase) {
|
||||||
|
return "high"
|
||||||
|
}
|
||||||
|
let i = i + 1
|
||||||
|
}
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
|
||||||
fn safety_detect_bell_level(message: String) -> String {
|
fn safety_detect_bell_level(message: String) -> String {
|
||||||
let text: String = safety_normalize(message)
|
let text: String = safety_normalize(message)
|
||||||
let is_hard: Bool = safety_any_match(text, safety_self_harm_phrases())
|
let is_hard: Bool = safety_any_match(text, safety_self_harm_phrases())
|
||||||
|
|||||||
@@ -162,6 +162,75 @@ fn load_identity_context() -> Void {
|
|||||||
println("[soul] persona node loaded (" + int_to_str(str_len(p_content)) + " chars)")
|
println("[soul] persona node loaded (" + int_to_str(str_len(p_content)) + " chars)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cross-session affective context: load BellEvent and PositiveEvent nodes from last 7 days.
|
||||||
|
let aff_now: Int = time_now()
|
||||||
|
let aff_7d: Int = aff_now - 604800
|
||||||
|
let bell_raw: String = engram_search_json("bell:soft bell:hard BellEvent affective", 3)
|
||||||
|
let bell_aff_ok: Bool = !str_eq(bell_raw, "") && !str_eq(bell_raw, "[]")
|
||||||
|
let aff_ctx: String = ""
|
||||||
|
let aff_ctx = if bell_aff_ok {
|
||||||
|
let bn_total: Int = json_array_len(bell_raw)
|
||||||
|
let bacc: String = ""
|
||||||
|
let bi: Int = 0
|
||||||
|
let bacc = while bi < bn_total {
|
||||||
|
let bn: String = json_array_get(bell_raw, bi)
|
||||||
|
let bn_c: String = json_get(bn, "content")
|
||||||
|
let bm: String = " | ts:"
|
||||||
|
let bmp: Int = str_index_of(bn_c, bm)
|
||||||
|
let bn_ts_raw: String = if bmp >= 0 {
|
||||||
|
let bs: Int = bmp + str_len(bm)
|
||||||
|
let br: String = str_slice(bn_c, bs, str_len(bn_c))
|
||||||
|
let bn_next: Int = str_index_of(br, " | ")
|
||||||
|
if bn_next < 0 { br } else { str_slice(br, 0, bn_next) }
|
||||||
|
} else {
|
||||||
|
let bca: String = json_get(bn, "created_at")
|
||||||
|
if str_eq(bca, "") { json_get(bn, "updated_at") } else { bca }
|
||||||
|
}
|
||||||
|
let bn_ts: Int = if str_eq(bn_ts_raw, "") { 0 } else { str_to_int(bn_ts_raw) }
|
||||||
|
let snip: String = if str_len(bn_c) > 200 { str_slice(bn_c, 0, 200) } else { bn_c }
|
||||||
|
let bacc = if bn_ts >= aff_7d && !str_eq(snip, "") {
|
||||||
|
if str_eq(bacc, "") { snip } else { bacc + "\n" + snip }
|
||||||
|
} else { bacc }
|
||||||
|
let bi = bi + 1
|
||||||
|
bacc
|
||||||
|
}
|
||||||
|
bacc
|
||||||
|
} else { "" }
|
||||||
|
let pos_raw: String = engram_search_json("PositiveEvent joy:high joy:low affective", 3)
|
||||||
|
let pos_aff_ok: Bool = !str_eq(pos_raw, "") && !str_eq(pos_raw, "[]")
|
||||||
|
let aff_ctx = if pos_aff_ok {
|
||||||
|
let pn_total: Int = json_array_len(pos_raw)
|
||||||
|
let pacc: String = aff_ctx
|
||||||
|
let pi: Int = 0
|
||||||
|
let pacc = while pi < pn_total {
|
||||||
|
let pn: String = json_array_get(pos_raw, pi)
|
||||||
|
let pn_c: String = json_get(pn, "content")
|
||||||
|
let pm: String = " | ts:"
|
||||||
|
let pmp: Int = str_index_of(pn_c, pm)
|
||||||
|
let pn_ts_raw: String = if pmp >= 0 {
|
||||||
|
let ps: Int = pmp + str_len(pm)
|
||||||
|
let pr: String = str_slice(pn_c, ps, str_len(pn_c))
|
||||||
|
let pn_next: Int = str_index_of(pr, " | ")
|
||||||
|
if pn_next < 0 { pr } else { str_slice(pr, 0, pn_next) }
|
||||||
|
} else {
|
||||||
|
let pca: String = json_get(pn, "created_at")
|
||||||
|
if str_eq(pca, "") { json_get(pn, "updated_at") } else { pca }
|
||||||
|
}
|
||||||
|
let pn_ts: Int = if str_eq(pn_ts_raw, "") { 0 } else { str_to_int(pn_ts_raw) }
|
||||||
|
let psnip: String = if str_len(pn_c) > 200 { str_slice(pn_c, 0, 200) } else { pn_c }
|
||||||
|
let pacc = if pn_ts >= aff_7d && !str_eq(psnip, "") {
|
||||||
|
if str_eq(pacc, "") { psnip } else { pacc + "\n" + psnip }
|
||||||
|
} else { pacc }
|
||||||
|
let pi = pi + 1
|
||||||
|
pacc
|
||||||
|
}
|
||||||
|
pacc
|
||||||
|
} else { aff_ctx }
|
||||||
|
if !str_eq(aff_ctx, "") {
|
||||||
|
state_set("soul_affective_context", aff_ctx)
|
||||||
|
println("[soul] affective context loaded (" + int_to_str(str_len(aff_ctx)) + " chars)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// seed_persona_from_env — one-time migration: SOUL_IDENTITY env var → Persona graph node.
|
// seed_persona_from_env — one-time migration: SOUL_IDENTITY env var → Persona graph node.
|
||||||
@@ -320,14 +389,53 @@ fn layered_cycle(raw_input: String) -> String {
|
|||||||
json_get(steward_result, "redirect_to")
|
json_get(steward_result, "redirect_to")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISSUE 1: pre-LLM bell augmentation for layered_cycle path.
|
// L2c: affective context injection.
|
||||||
// safety_augment_system appends soft/hard directive to system prompt when bell fires,
|
let lc_aff_cutoff: Int = time_now() - 259200
|
||||||
// ensuring LLM processes message WITH the safety directive -- not just post-output gate.
|
let lc_bell_nodes: String = engram_search_json("bell:soft bell:hard BellEvent affective", 2)
|
||||||
// Stored in state as "layered_cycle_safety_system_addendum" for imprint_respond to use.
|
let lc_has_bell: Bool = !str_eq(lc_bell_nodes, "") && !str_eq(lc_bell_nodes, "[]")
|
||||||
// TODO: wire directly when imprint_respond gains system_override param (imprint.el change).
|
let lc_bell_note: String = if lc_has_bell {
|
||||||
// ISSUE 3 TODO: no semantic crisis detection. Keyword-only means signals that evade
|
let lb0: String = json_array_get(lc_bell_nodes, 0)
|
||||||
// the phrase list pass with zero augmentation. Semantic layer = separate decision.
|
let lb_c: String = json_get(lb0, "content")
|
||||||
|
let lbm: String = " | ts:"
|
||||||
|
let lbmp: Int = str_index_of(lb_c, lbm)
|
||||||
|
let lb_ts_raw: String = if lbmp >= 0 {
|
||||||
|
let lbs: Int = lbmp + str_len(lbm)
|
||||||
|
let lbr: String = str_slice(lb_c, lbs, str_len(lb_c))
|
||||||
|
let lbn: Int = str_index_of(lbr, " | ")
|
||||||
|
if lbn < 0 { lbr } else { str_slice(lbr, 0, lbn) }
|
||||||
|
} else {
|
||||||
|
let lbca: String = json_get(lb0, "created_at")
|
||||||
|
if str_eq(lbca, "") { json_get(lb0, "updated_at") } else { lbca }
|
||||||
|
}
|
||||||
|
let lb_ts: Int = if str_eq(lb_ts_raw, "") { 0 } else { str_to_int(lb_ts_raw) }
|
||||||
|
if lb_ts > lc_aff_cutoff { "[AFFECTIVE NOTE: User was in distress in a recent session.]" } else { "" }
|
||||||
|
} else { "" }
|
||||||
|
let lc_pos_nodes: String = engram_search_json("PositiveEvent joy:high joy:low affective", 2)
|
||||||
|
let lc_has_pos: Bool = !str_eq(lc_pos_nodes, "") && !str_eq(lc_pos_nodes, "[]")
|
||||||
|
let lc_pos_note: String = if lc_has_pos && str_eq(lc_bell_note, "") {
|
||||||
|
let lp0: String = json_array_get(lc_pos_nodes, 0)
|
||||||
|
let lp_c: String = json_get(lp0, "content")
|
||||||
|
let lpm: String = " | ts:"
|
||||||
|
let lpmp: Int = str_index_of(lp_c, lpm)
|
||||||
|
let lp_ts_raw: String = if lpmp >= 0 {
|
||||||
|
let lps: Int = lpmp + str_len(lpm)
|
||||||
|
let lpr: String = str_slice(lp_c, lps, str_len(lp_c))
|
||||||
|
let lpn: Int = str_index_of(lpr, " | ")
|
||||||
|
if lpn < 0 { lpr } else { str_slice(lpr, 0, lpn) }
|
||||||
|
} else {
|
||||||
|
let lpca: String = json_get(lp0, "created_at")
|
||||||
|
if str_eq(lpca, "") { json_get(lp0, "updated_at") } else { lpca }
|
||||||
|
}
|
||||||
|
let lp_ts: Int = if str_eq(lp_ts_raw, "") { 0 } else { str_to_int(lp_ts_raw) }
|
||||||
|
if lp_ts > lc_aff_cutoff { "[AFFECTIVE NOTE: User shared positive news in a recent session.]" } else { "" }
|
||||||
|
} else { "" }
|
||||||
|
let lc_affective_note: String = if !str_eq(lc_bell_note, "") { lc_bell_note } else { lc_pos_note }
|
||||||
|
|
||||||
|
// pre-LLM bell augmentation
|
||||||
let augmented_addendum: String = safety_augment_system("", raw_input)
|
let augmented_addendum: String = safety_augment_system("", raw_input)
|
||||||
|
let augmented_addendum = if str_eq(lc_affective_note, "") { augmented_addendum } else {
|
||||||
|
if str_eq(augmented_addendum, "") { lc_affective_note } else { lc_affective_note + "\n" + augmented_addendum }
|
||||||
|
}
|
||||||
state_set("layered_cycle_safety_system_addendum", augmented_addendum)
|
state_set("layered_cycle_safety_system_addendum", augmented_addendum)
|
||||||
|
|
||||||
// L3: imprint responds
|
// L3: imprint responds
|
||||||
|
|||||||
Reference in New Issue
Block a user