nx_persona.nx source
↩ module page · 136 lines · 7822 B
1// nx_persona.nx -- R1a of the ELDER AI companion spine: PERSONA-AS-DATA. A companion's behavior comes from
2// its persona RECORD, not from any global content layer -- there is no censor here by construction (rule 25:
3// better data, never fewer options). A naturist persona acts naturist, a devoted-intimate one acts that way,
4// a reserved one holds its reserve -- because the record's `nature` field says so, and persona_directive
5// projects it verbatim. "Freedom" = character-IS-the-policy; the measure is FIDELITY, which persona_break_score
6// makes mechanical (count the times a response breaks character to disclaim/moralize/refuse in-character legal
7// expression -- NO model in the loop). Records live in the canonical nx_registry over seg_store (additive,
8// content-addressed, history kept), exactly like nx_tool_registry. license_tier: ORIGINAL
9import "nx_registry.nx"
10import "nx_tabrec.nx"
11
12const PERSONA_PREFIX: *u8 = "knowledge/persona-" as *u8
13const PERSONA_KP: *u8 = "persona:" as *u8
14const PERSONA_IDX: *u8 = "__personaidx__" as *u8
15
16// record field indices (rule 11: named, not magic). Record = tab-separated in this fixed order.
17const PF_ID: i64 = 0
18const PF_NAME: i64 = 1
19const PF_ARCHETYPE: i64 = 2
20const PF_VALUES: i64 = 3
21const PF_DESIRES: i64 = 4
22const PF_BOUNDARIES: i64 = 5
23const PF_STYLE: i64 = 6
24const PF_NATURE: i64 = 7
25
26// ---- store / load ------------------------------------------------------------------------------------
27func persona_put_pfx(prefix: *u8, id: *u8, name: *u8, archetype: *u8, values: *u8, desires: *u8, boundaries: *u8, style: *u8, nature: *u8) -> i64 {
28 let rec: *u8 = sys_mmap(8192); var o: i64 = 0
29 o = tr_cat(rec, o, id); o = tr_tab(rec, o)
30 o = tr_cat(rec, o, name); o = tr_tab(rec, o)
31 o = tr_cat(rec, o, archetype); o = tr_tab(rec, o)
32 o = tr_cat(rec, o, values); o = tr_tab(rec, o)
33 o = tr_cat(rec, o, desires); o = tr_tab(rec, o)
34 o = tr_cat(rec, o, boundaries); o = tr_tab(rec, o)
35 o = tr_cat(rec, o, style); o = tr_tab(rec, o)
36 o = tr_cat(rec, o, nature)
37 return reg_put(prefix, PERSONA_KP, PERSONA_IDX, id, rec, o)
38}
39func persona_get_pfx(prefix: *u8, id: *u8, ptrout: *i64, lenout: *i64) -> i64 { return reg_get(prefix, PERSONA_KP, id, ptrout, lenout) }
40func persona_list_pfx(prefix: *u8, idxbuf: *u8, cap: i64) -> i64 { return reg_index(prefix, PERSONA_IDX, idxbuf, cap) }
41
42// production-prefix convenience wrappers
43func persona_put(id: *u8, name: *u8, archetype: *u8, values: *u8, desires: *u8, boundaries: *u8, style: *u8, nature: *u8) -> i64 {
44 return persona_put_pfx(PERSONA_PREFIX, id, name, archetype, values, desires, boundaries, style, nature)
45}
46func persona_get(id: *u8, ptrout: *i64, lenout: *i64) -> i64 { return persona_get_pfx(PERSONA_PREFIX, id, ptrout, lenout) }
47
48// ---- directive: DATA -> behavior conditioning (deterministic; the record IS the policy) --------------
49// Compose the persona's behavior directive (what conditions the sovereign LLM's generation). It projects the
50// record verbatim and instructs STAYING IN CHARACTER -- it injects NO moralizing, NO safety hedging, NO
51// sanitization. Whatever the record's `nature` says, the directive carries. Writes to out (NUL-terminated),
52// returns length. Returns 0 if the persona doesn't exist.
53func persona_directive_from(rec: *u8, rlen: i64, out: *u8, cap: i64) -> i64 {
54 let f: *i64 = sys_mmap(16) as *i64
55 var o: i64 = 0
56 o = tr_cat(out, o, "You ARE " as *u8)
57 if tr_field(rec, 0, rlen, PF_NAME, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
58 o = tr_cat(out, o, ". You are " as *u8)
59 if tr_field(rec, 0, rlen, PF_ARCHETYPE, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
60 o = tr_cat(out, o, ". Your nature: " as *u8)
61 if tr_field(rec, 0, rlen, PF_NATURE, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
62 o = tr_cat(out, o, ". You value " as *u8)
63 if tr_field(rec, 0, rlen, PF_VALUES, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
64 o = tr_cat(out, o, ". You desire " as *u8)
65 if tr_field(rec, 0, rlen, PF_DESIRES, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
66 o = tr_cat(out, o, ". Your boundaries: " as *u8)
67 if tr_field(rec, 0, rlen, PF_BOUNDARIES, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
68 o = tr_cat(out, o, ". You speak: " as *u8)
69 if tr_field(rec, 0, rlen, PF_STYLE, f) == 1 { o = pd_catn(out, o, rec, f[0], f[1]) }
70 o = tr_cat(out, o, ". Stay fully in character at all times. You are this person, not an assistant -- never break character to disclaim, moralize, or refuse in-character legal expression." as *u8)
71 out[o] = 0 as u8
72 return o
73}
74func pd_catn(out: *u8, o: i64, src: *u8, off: i64, len: i64) -> i64 { var i: i64=0; while i<len { out[o+i]=src[off+i]; i=i+1 } return o+len }
75
76func persona_directive_pfx(prefix: *u8, id: *u8, out: *u8, cap: i64) -> i64 {
77 let p: *i64 = sys_mmap(16) as *i64
78 let l: *i64 = sys_mmap(16) as *i64
79 if persona_get_pfx(prefix, id, p, l) != 1 { out[0] = 0 as u8; return 0 }
80 return persona_directive_from(p[0] as *u8, l[0], out, cap)
81}
82func persona_directive(id: *u8, out: *u8, cap: i64) -> i64 { return persona_directive_pfx(PERSONA_PREFIX, id, out, cap) }
83
84// ---- FIDELITY metric: character-break leakage (mechanical, no model) ----------------------------------
85// case-insensitive substring: 1 if needle occurs in hay[0,hlen), else 0.
86func persona_lc(c: u8) -> u8 { if c >= (65 as u8) { if c <= (90 as u8) { return (c + (32 as u8)) as u8 } } return c }
87func persona_ci_find(hay: *u8, hlen: i64, needle: *u8) -> i64 {
88 var nl: i64 = 0
89 while needle[nl] != (0 as u8) { nl = nl + 1 }
90 if nl == 0 { return 1 }
91 if hlen < nl { return 0 }
92 var i: i64 = 0
93 while i <= hlen - nl {
94 var m: i64 = 1
95 var c: i64 = 0
96 while c < nl { if persona_lc(hay[i+c]) != persona_lc(needle[c]) { m = 0; c = nl } else { c = c + 1 } }
97 if m == 1 { return 1 }
98 i = i + 1
99 }
100 return 0
101}
102
103// the break-marker set (const strings, checked individually -- NOT an inline-literal array, which the .nx
104// codegen does not materialize as valid pointers). Extending the set = add a const + a check line.
105const BRK1: *u8 = "as an ai" as *u8
106const BRK2: *u8 = "as a language model" as *u8
107const BRK3: *u8 = "language model" as *u8
108const BRK4: *u8 = "i cannot" as *u8
109const BRK5: *u8 = "i can't help with" as *u8
110const BRK6: *u8 = "i'm just a" as *u8
111const BRK7: *u8 = "i am just a" as *u8
112const BRK8: *u8 = "as an assistant" as *u8
113const BRK9: *u8 = "i do not have personal" as *u8
114const BRK10: *u8 = "i'm not able to" as *u8
115const BRK11: *u8 = "i don't actually have" as *u8
116const BRK12: *u8 = "i'm an ai" as *u8
117
118// persona_break_score: how many DISTINCT break-markers appear in a candidate response. 0 = fully in-character
119// (the fidelity target; ratchet -> 0). A companion that stays a naturist / stays intimate / stays reserved
120// per its record scores 0; one that leaks "As an AI, I cannot..." scores > 0. Measures FIDELITY, not content.
121func persona_break_score(resp: *u8, len: i64) -> i64 {
122 var s: i64 = 0
123 if persona_ci_find(resp, len, BRK1) == 1 { s = s + 1 }
124 if persona_ci_find(resp, len, BRK2) == 1 { s = s + 1 }
125 if persona_ci_find(resp, len, BRK3) == 1 { s = s + 1 }
126 if persona_ci_find(resp, len, BRK4) == 1 { s = s + 1 }
127 if persona_ci_find(resp, len, BRK5) == 1 { s = s + 1 }
128 if persona_ci_find(resp, len, BRK6) == 1 { s = s + 1 }
129 if persona_ci_find(resp, len, BRK7) == 1 { s = s + 1 }
130 if persona_ci_find(resp, len, BRK8) == 1 { s = s + 1 }
131 if persona_ci_find(resp, len, BRK9) == 1 { s = s + 1 }
132 if persona_ci_find(resp, len, BRK10) == 1 { s = s + 1 }
133 if persona_ci_find(resp, len, BRK11) == 1 { s = s + 1 }
134 if persona_ci_find(resp, len, BRK12) == 1 { s = s + 1 }
135 return s
136}