2ea1d50fa3
Neuron Soul CI / build (pull_request) Successful in 5m10s
Tooling built on Tim's machine to run Neuron from the terminal as a
Claude Code session (identity + graph memory + agency) instead of
relaying to the soul's /api/chat.
- cli/neuron_recall.py BM25 read over the engram snapshot + CLI memories
(works around pinned-only soul search)
- cli/neuron_remember.py reliable local memory writes with read-back verify
(works around the corrupting capture endpoint)
- cli/neuron-chat.py standalone direct-chat REPL with per-turn memory injection
- cli/neuron_mcp.py stdlib MCP server (chat/search) with graceful degradation
- cli/CLAUDE.md.example the operating identity that makes Claude Code run as Neuron
- cli/HANDOFF.md soul-side bugs to fix so this becomes unnecessary
Scaffolding/proposal - intended to be retired once the soul does native
retrieval, correct persistence, and a real CLI identity/voice surface.
Pairs with the runtime model-passthrough + UTF-8 fixes in the el repo.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
2.2 KiB
Python
62 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
neuron_remember — Neuron's memory write path (save as you go).
|
|
|
|
Appends a memory to ~/.neuron/neuron-cli-memories.jsonl, a reliable local store
|
|
that neuron_recall.py indexes alongside the graph. Used because the soul's own
|
|
capture path corrupts/loses writes. These can later be synced into the engram
|
|
graph once the soul's write path is fixed.
|
|
|
|
Usage:
|
|
python3 ~/neuron_remember.py "Tim prefers X because Y" lesson
|
|
python3 ~/neuron_remember.py "<observation>" # tier defaults to note
|
|
|
|
Tiers (Neuron's memory-philosophy): note -> lesson -> canonical
|
|
"""
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
MEMS = os.path.expanduser("~/.neuron/neuron-cli-memories.jsonl")
|
|
VALID_TIERS = ("note", "lesson", "canonical")
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2 or not sys.argv[1].strip():
|
|
print("usage: neuron_remember.py \"<observation>\" [note|lesson|canonical]")
|
|
return 1
|
|
content = sys.argv[1].strip()
|
|
tier = sys.argv[2].strip().lower() if len(sys.argv) > 2 else "note"
|
|
if tier not in VALID_TIERS:
|
|
tier = "note"
|
|
|
|
ts = int(time.time())
|
|
mid = "ncli-" + hashlib.sha1(f"{ts}:{content}".encode()).hexdigest()[:12]
|
|
rec = {"id": mid, "ts": ts, "tier": tier, "content": content}
|
|
|
|
os.makedirs(os.path.dirname(MEMS), exist_ok=True)
|
|
# dedupe: skip if identical content already saved
|
|
if os.path.exists(MEMS):
|
|
for line in open(MEMS, encoding="utf-8", errors="replace"):
|
|
try:
|
|
if json.loads(line).get("content") == content:
|
|
print(f"(already remembered: {mid})")
|
|
return 0
|
|
except Exception:
|
|
pass
|
|
with open(MEMS, "a", encoding="utf-8") as f:
|
|
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
|
|
|
|
# read-back verify (never claim a save that didn't land)
|
|
ok = any(json.loads(l).get("id") == mid
|
|
for l in open(MEMS, encoding="utf-8", errors="replace") if l.strip())
|
|
total = sum(1 for l in open(MEMS, encoding="utf-8", errors="replace") if l.strip())
|
|
print(f"{'saved' if ok else 'FAILED'} [{tier}] {mid} (neuron memories: {total})")
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|