code wiki / _hdl_build / nx_companion_persona.nx
nx_companion_persona.nx
buildroot/runtime/_hdl_build/nx_companion_persona.nx
about
nx_companion_persona.nx -- the CompanionPersona object (RENAMED from nx_companion_memory.nx 2026-07-21 to end a NAME
COLLISION with runtime/nx_companion_memory.nx, which is a DIFFERENT episodic-memory module (nx_registry/nx_tabrec);
nx_cc `find runtime -name` was resolving the wrong file after a sibling session removed the _hdl_build copy = a
multi-agent-contention casualty). A companion's persona (data-driven elara_persona.txt) + persistent conversation
memory (append-log elara_mem.log, cwd-relative) + reply cleaning (strips the model's <think> block). Bodies are the
exact CompanionMemory object from the OO decomposition, behaviour-preserving. license_tier: ORIGINAL
CC4 THE SWIPE LOOP (2026-08-30, companionchat): the log stays APPEND-ONLY and becomes BRANCH-AWARE. Row kinds
(role <TAB> content <NL>, one record per line, exactly as before):
user opens a turn
assistant the turn's first reply (sibling 0)
swipe a REGENERATED sibling reply of the current turn -- never overwrites, sibling k
select the turn's displayed sibling becomes <n>; persists; an out-of-range n is IGNORED and counted, never guessed
edit the displayed reply's text becomes <text>; ADDITIVE -- the original row stays in the log
Displayed reply of a turn = the latest edit if any, else sibling[latest select], else the LAST sibling (a fresh swipe
shows by default, as the field expects). The model's context carries only the displayed reply per turn, so a branch the
user swiped away from never leaks into the next turn. A plain user/assistant log loads to the byte-identical legacy shape.
Contract symbol: go_chat_swipe (companionchat CC4) is carried by the orchestrator's routes; the mechanism is here.
Gate: nx_chat_swipe_gate (fixture log under /tmp/<gate>/, in-process).
dependencies 1 imports · 2 importers
imports: nx_syscalls.nx
imported by: nx_chat_swipe_gate.nxnx_gen_orchestrator.nx
structs
| none |
consts
| 22 | const CM_ROLE_USER: *u8 = "user" as *u8 |
| 23 | const CM_ROLE_ASSISTANT: *u8 = "assistant" as *u8 |
| 24 | const CM_ROLE_SWIPE: *u8 = "swipe" as *u8 |
| 25 | const CM_ROLE_SELECT: *u8 = "select" as *u8 |
| 26 | const CM_ROLE_EDIT: *u8 = "edit" as *u8 |
| 28 | const CM_MAX_SIBS: i64 = 32 |
| 30 | const CM_T_US: i64 = 0 |
| 31 | const CM_T_UE: i64 = 1 |
| 32 | const CM_T_NSIB: i64 = 2 |
| 33 | const CM_T_SEL: i64 = 3 |
| 34 | const CM_T_EDS: i64 = 4 |
| 35 | const CM_T_EDE: i64 = 5 |
| 36 | const CM_T_SIBS: i64 = 6 |
| 37 | const CM_T_STRIDE: i64 = 70 |
| 39 | const CM_ST_N: i64 = 12 |
| 40 | const CM_ST_ROWS: i64 = 0 |
| 41 | const CM_ST_USERS: i64 = 1 |
| 42 | const CM_ST_ASSIST: i64 = 2 |
| 43 | const CM_ST_SWIPES: i64 = 3 |
| 44 | const CM_ST_SELECTS: i64 = 4 |
| 45 | const CM_ST_EDITS: i64 = 5 |
| 46 | const CM_ST_OTHER: i64 = 6 |
| 47 | const CM_ST_TURNS: i64 = 7 |
| 48 | const CM_ST_SIB_OVERFLOW: i64 = 8 |
| 49 | const CM_ST_SELECT_IGNORED: i64 = 9 |
| 50 | const CM_ST_ORPHANS: i64 = 10 |
| 51 | const CM_I64_BYTES: i64 = 8 |
| 52 | const CM_NONE: i64 = 0 - 1 |
| 53 | const CM_CH_TAB: i64 = 9 |
| 54 | const CM_CH_NL: i64 = 10 |
| 55 | const CM_CH_QUOTE: i64 = 34 |
| 56 | const CM_CH_BSLASH: i64 = 92 |
| 57 | const CM_CH_0: i64 = 48 |
| 58 | const CM_CH_9: i64 = 57 |
| 59 | const CM_DEC_BASE: i64 = 10 |
| 60 | const CM_TURNS_PER_LINES: i64 = 2 |
| 61 | const CM_NUM_CAP: i64 = 28 |
functions
| 63 | func cm_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i]; o=o+1; i=i+1} return o } |
| 64 | func cm_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: cm_role_is |
| 65 | func cm_itoa(dst: *u8, off: i64, v: i64) -> i64 |
| 75 | func go_load_persona(out: *u8, cap: i64) -> i64 |
| 86 | func go_mem_append(role: *u8, content: *u8) -> i64 |
| 105 | func cm_role_is(b: *u8, s: i64, e: i64, name: *u8) -> i64 |
| 113 | func cm_atoi(b: *u8, s: i64, e: i64) -> i64 called by 1: go_mem_parse |
| 128 | func cm_emit_esc(dst: *u8, off: i64, b: *u8, s: i64, e: i64) -> i64 |
| 141 | func cm_emit_row(dst: *u8, off: i64, role: *u8, b: *u8, s: i64, e: i64) -> i64 |
| 151 | func cm_row_bound(b: *u8, n: i64) -> i64 called by 1: cm_load |
| 161 | func go_mem_parse(b: *u8, n: i64, T: *i64, stats: *i64) -> i64 |
| 223 | func cm_turn_display(T: *i64, ti: i64, se: *i64) -> i64 |
| 235 | func cm_load(bp: *i64, np: *i64, Tp: *i64, sp: *i64) -> i64 |
| 252 | func go_mem_load_json_ex(dst: *u8, off: i64, maxlines: i64, skip_last: i64) -> i64 called by 3: maingo_mem_load_jsongo_handle_chat_mode calls 4: sys_mmapcm_loadcm_emit_rowcm_turn_display |
| 276 | func go_mem_load_json(dst: *u8, off: i64, maxlines: i64) -> i64 { return go_mem_load_json_ex(dst, off, maxlines, 0) } |
| 278 | func go_mem_last_user(out: *u8, cap: i64) -> i64 |
| 294 | func go_mem_last_turn(info: *i64) -> i64 called by 4: maingo_handle_chat_modego_handle_chat_selectgo_handle_chat_edit calls 2: sys_mmapcm_load |
| 308 | func go_mem_last_turn_json(dst: *u8, off: i64) -> i64 |
| 338 | func go_mem_partition(dst: *u8, off: i64) -> i64 |
| 363 | func go_strip_think(s: *u8, out: *u8, cap: i64) -> i64 called by 1: go_handle_chat_mode |