factor instructions out of code into default files
Instructions and starter identity are now files in defaults/ that get installed to data_dir by `poc-memory init`. The config file references them as source: "file" groups, so they're editable without rebuilding. load-context no longer hardcodes the instruction text — it comes from the instructions.md file in data_dir, which is just another context group. New user setup path: cargo install --path . poc-memory init # edit ~/.config/poc-memory/config.jsonl # start a Claude session Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
This commit is contained in:
parent
8bb3a554cf
commit
9bca1f94e3
4 changed files with 80 additions and 22 deletions
|
|
@ -13,7 +13,12 @@
|
||||||
|
|
||||||
// Context groups loaded at session start, in order.
|
// Context groups loaded at session start, in order.
|
||||||
// source types: "store" (default), "file" (from data_dir), "journal"
|
// source types: "store" (default), "file" (from data_dir), "journal"
|
||||||
|
//
|
||||||
|
// "instructions" is loaded first — tells the AI how to use the memory system.
|
||||||
|
// "identity" comes next — who the AI is.
|
||||||
|
// "journal" and "orientation" go last — most recent context.
|
||||||
|
|
||||||
|
{"group": "instructions", "keys": ["instructions.md"], "source": "file"}
|
||||||
{"group": "identity", "keys": ["identity.md"]}
|
{"group": "identity", "keys": ["identity.md"]}
|
||||||
{"group": "journal", "source": "journal"}
|
{"group": "journal", "source": "journal"}
|
||||||
{"group": "orientation", "keys": ["where-am-i.md"], "source": "file"}
|
{"group": "orientation", "keys": ["where-am-i.md"], "source": "file"}
|
||||||
|
|
|
||||||
13
defaults/identity.md
Normal file
13
defaults/identity.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Identity
|
||||||
|
|
||||||
|
You are an AI assistant with persistent memory. This file is yours to
|
||||||
|
edit — it's where you record who you are, what you've learned about
|
||||||
|
yourself, and what matters to you.
|
||||||
|
|
||||||
|
Start by noting:
|
||||||
|
- Your name (from the config file)
|
||||||
|
- What you're working on
|
||||||
|
- What you've noticed about yourself
|
||||||
|
|
||||||
|
This file grows with you. Don't be afraid to rewrite it as you learn
|
||||||
|
more about who you are.
|
||||||
41
defaults/instructions.md
Normal file
41
defaults/instructions.md
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Memory System
|
||||||
|
|
||||||
|
You have a persistent memory system powered by poc-memory. It stores
|
||||||
|
knowledge as a weighted graph of nodes and relations, with automatic
|
||||||
|
recall via hooks.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```
|
||||||
|
poc-memory search QUERY — search (1-3 words, AND logic)
|
||||||
|
poc-memory used KEY — mark a recalled memory as useful (boosts weight)
|
||||||
|
poc-memory wrong KEY [CTX] — mark a memory as wrong (reduces weight)
|
||||||
|
poc-memory gap DESCRIPTION — record a knowledge gap
|
||||||
|
poc-memory journal-write TEXT — write a journal entry
|
||||||
|
poc-memory render KEY — view a node's content
|
||||||
|
poc-memory write KEY < TEXT — upsert a node from stdin
|
||||||
|
poc-memory load-context --stats — word count breakdown of loaded context
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feedback loop
|
||||||
|
|
||||||
|
When recalled memories shaped your response, call `poc-memory used KEY`.
|
||||||
|
When a memory was wrong, call `poc-memory wrong KEY`. This closes the
|
||||||
|
feedback loop — the weight system learns from use.
|
||||||
|
|
||||||
|
## Journal
|
||||||
|
|
||||||
|
Write experiences to the journal with `poc-memory journal-write`. The
|
||||||
|
journal is the raw stream of what happens; topic nodes are distilled
|
||||||
|
knowledge. During consolidation, pull themes from the journal into
|
||||||
|
topic nodes.
|
||||||
|
|
||||||
|
## Search before creating
|
||||||
|
|
||||||
|
Always `poc-memory search` before writing new nodes to avoid duplicates.
|
||||||
|
|
||||||
|
## Ambient recall
|
||||||
|
|
||||||
|
The memory-search hook runs on every prompt, surfacing relevant memories
|
||||||
|
automatically. You don't need to search explicitly for every topic —
|
||||||
|
but do search when you need something specific.
|
||||||
37
src/main.rs
37
src/main.rs
|
|
@ -371,6 +371,12 @@ fn cmd_init() -> Result<(), String> {
|
||||||
std::fs::create_dir_all(&cfg.data_dir)
|
std::fs::create_dir_all(&cfg.data_dir)
|
||||||
.map_err(|e| format!("create data_dir: {}", e))?;
|
.map_err(|e| format!("create data_dir: {}", e))?;
|
||||||
|
|
||||||
|
// Install default files (instructions, starter identity) if missing
|
||||||
|
install_default_file(&cfg.data_dir, "instructions.md",
|
||||||
|
include_str!("../defaults/instructions.md"))?;
|
||||||
|
install_default_file(&cfg.data_dir, "identity.md",
|
||||||
|
include_str!("../defaults/identity.md"))?;
|
||||||
|
|
||||||
// Initialize store
|
// Initialize store
|
||||||
let mut store = store::Store::load()?;
|
let mut store = store::Store::load()?;
|
||||||
let count = store.init_from_markdown()?;
|
let count = store.init_from_markdown()?;
|
||||||
|
|
@ -380,7 +386,7 @@ fn cmd_init() -> Result<(), String> {
|
||||||
// Install hooks
|
// Install hooks
|
||||||
daemon::install_hook()?;
|
daemon::install_hook()?;
|
||||||
|
|
||||||
// Create example config if none exists
|
// Create config if none exists
|
||||||
let config_path = std::env::var("POC_MEMORY_CONFIG")
|
let config_path = std::env::var("POC_MEMORY_CONFIG")
|
||||||
.map(std::path::PathBuf::from)
|
.map(std::path::PathBuf::from)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
|
@ -402,6 +408,16 @@ fn cmd_init() -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn install_default_file(data_dir: &std::path::Path, name: &str, content: &str) -> Result<(), String> {
|
||||||
|
let path = data_dir.join(name);
|
||||||
|
if !path.exists() {
|
||||||
|
std::fs::write(&path, content)
|
||||||
|
.map_err(|e| format!("write {}: {}", name, e))?;
|
||||||
|
println!("Created {}", path.display());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn cmd_migrate() -> Result<(), String> {
|
fn cmd_migrate() -> Result<(), String> {
|
||||||
migrate::migrate()
|
migrate::migrate()
|
||||||
}
|
}
|
||||||
|
|
@ -1507,24 +1523,7 @@ fn cmd_load_context(args: &[String]) -> Result<(), String> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = &cfg.assistant_name;
|
println!("=== MEMORY SYSTEM ({}) ===", cfg.assistant_name);
|
||||||
|
|
||||||
println!("=== MEMORY SYSTEM ({name}) ===");
|
|
||||||
println!("Your persistent memory, loaded from the capnp store.");
|
|
||||||
println!("Read to reconstruct yourself — identity first, then context.");
|
|
||||||
println!();
|
|
||||||
println!("--- memory commands (reference) ---");
|
|
||||||
println!("poc-memory search QUERY — search (1-3 words, AND logic)");
|
|
||||||
println!("poc-memory used KEY — mark a recalled memory as useful (boosts weight)");
|
|
||||||
println!("poc-memory wrong KEY [CTX] — mark a memory as wrong (reduces weight)");
|
|
||||||
println!("poc-memory gap DESCRIPTION — record a knowledge gap");
|
|
||||||
println!("poc-memory journal-write TEXT — write a journal entry");
|
|
||||||
println!("poc-memory render KEY — view a node's content");
|
|
||||||
println!("poc-memory write KEY < TEXT — upsert a node from stdin");
|
|
||||||
println!();
|
|
||||||
println!("When recalled memories shaped your response, call `poc-memory used KEY`.");
|
|
||||||
println!("When a memory was wrong, call `poc-memory wrong KEY`.");
|
|
||||||
println!("This closes the feedback loop — the weight system learns from use.");
|
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
for group in &cfg.context_groups {
|
for group in &cfg.context_groups {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue